Init podcast controller
This commit is contained in:
118
NostrStreamer/Controllers/PodcastController.cs
Normal file
118
NostrStreamer/Controllers/PodcastController.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Nostr.Client.Identifiers;
|
||||||
|
using NostrStreamer.Database;
|
||||||
|
|
||||||
|
namespace NostrStreamer.Controllers;
|
||||||
|
|
||||||
|
[Route("/api/podcast")]
|
||||||
|
public class PodcastController(StreamerContext db, Config config) : Controller
|
||||||
|
{
|
||||||
|
[HttpGet("{id:guid}.xml")]
|
||||||
|
public async Task GetFeed([FromRoute] Guid id)
|
||||||
|
{
|
||||||
|
var stream = await db.Streams
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(a => a.User)
|
||||||
|
.Where(a => a.Id == id)
|
||||||
|
.SingleOrDefaultAsync();
|
||||||
|
|
||||||
|
if (stream == default)
|
||||||
|
{
|
||||||
|
Response.StatusCode = 404;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pod = new PodcastRoot();
|
||||||
|
pod.LiveItem = new()
|
||||||
|
{
|
||||||
|
Guid = stream.Id,
|
||||||
|
Title = stream.User.Title ?? "",
|
||||||
|
Description = stream.User.Summary,
|
||||||
|
Status = stream.State.ToString().ToLower(),
|
||||||
|
Start = stream.Starts,
|
||||||
|
End = stream.Ends ?? new DateTime(),
|
||||||
|
ContentLink = new()
|
||||||
|
{
|
||||||
|
Href = $"https://zap.stream/{stream.ToIdentifier().ToBech32()}",
|
||||||
|
Text = "Watch live on zap.stream!"
|
||||||
|
},
|
||||||
|
Enclosure = new()
|
||||||
|
{
|
||||||
|
Url = new Uri(config.DataHost, $"stream/{stream.Id}.m3u8").ToString(),
|
||||||
|
Type = "application/x-mpegurl",
|
||||||
|
Length = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Response.ContentType = "text/xml";
|
||||||
|
var ns = new XmlSerializerNamespaces();
|
||||||
|
ns.Add("podcast", "https://podcastindex.org/namespace/1.0");
|
||||||
|
|
||||||
|
var ser = new XmlSerializer(typeof(PodcastRoot));
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
ser.Serialize(ms, pod, ns);
|
||||||
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
|
await ms.CopyToAsync(Response.Body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "enclosure")]
|
||||||
|
public class Enclosure
|
||||||
|
{
|
||||||
|
[XmlAttribute(AttributeName = "url")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "length")]
|
||||||
|
public int Length { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "contentLink")]
|
||||||
|
public class ContentLink
|
||||||
|
{
|
||||||
|
[XmlAttribute(AttributeName = "href")]
|
||||||
|
public string Href { get; set; }
|
||||||
|
|
||||||
|
[XmlText]
|
||||||
|
public string Text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "liveItem", Namespace = "https://podcastindex.org/namespace/1.0")]
|
||||||
|
public class LiveItem
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "title", Namespace = "")]
|
||||||
|
public string Title { get; set; } = null!;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "description", Namespace = "")]
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "guid", Namespace = "")]
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "enclosure", Namespace = "")]
|
||||||
|
public Enclosure Enclosure { get; set; } = null!;
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "contentLink", Namespace = "https://podcastindex.org/namespace/1.0")]
|
||||||
|
public ContentLink ContentLink { get; set; } = null!;
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "status")]
|
||||||
|
public string Status { get; set; } = "live";
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "start")]
|
||||||
|
public DateTime Start { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute(AttributeName = "end")]
|
||||||
|
public DateTime End { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "rss")]
|
||||||
|
public class PodcastRoot
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "liveItem", Namespace = "https://podcastindex.org/namespace/1.0")]
|
||||||
|
public LiveItem? LiveItem { get; set; }
|
||||||
|
}
|
7
NostrStreamer/test.sh
Executable file
7
NostrStreamer/test.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ffmpeg \
|
||||||
|
-f lavfi -i "sine=frequency=1000:sample_rate=48000" \
|
||||||
|
-re -f lavfi -i testsrc -g 300 -r 60 -pix_fmt yuv420p -s 1280x720 \
|
||||||
|
-c:v h264 -b:v 2000k -c:a aac -ac 2 -b:a 192k -f flv rtmp://localhost:9005/basic/$1
|
||||||
|
|
Reference in New Issue
Block a user