Browse Source

feat: sync music video subtitles to next engine

pull/2917/head
Jason Dove 2 months ago
parent
commit
31d4e860b6
No known key found for this signature in database
  1. 47
      ErsatzTV.Application/Playouts/Commands/SyncNextPlayoutHandler.cs
  2. 7
      ErsatzTV.Application/Streaming/Queries/GetMusicVideoCreditsByPlayoutItemIdHandler.cs

47
ErsatzTV.Application/Playouts/Commands/SyncNextPlayoutHandler.cs

@ -304,6 +304,7 @@ public partial class SyncNextPlayoutHandler(
var audioVersion = new MediaItemAudioVersion(playoutItem.MediaItem, headVersion); var audioVersion = new MediaItemAudioVersion(playoutItem.MediaItem, headVersion);
await SelectTracks( await SelectTracks(
channel, channel,
playoutItem,
audioVersion, audioVersion,
nextPlayoutItem, nextPlayoutItem,
playoutItem.PreferredAudioLanguageCode ?? channel.PreferredAudioLanguageCode, playoutItem.PreferredAudioLanguageCode ?? channel.PreferredAudioLanguageCode,
@ -327,6 +328,7 @@ public partial class SyncNextPlayoutHandler(
private async Task SelectTracks( private async Task SelectTracks(
Channel channel, Channel channel,
PlayoutItem playoutItem,
MediaItemAudioVersion audioVersion, MediaItemAudioVersion audioVersion,
Core.Next.PlayoutItem nextPlayoutItem, Core.Next.PlayoutItem nextPlayoutItem,
string preferredAudioLanguage, string preferredAudioLanguage,
@ -335,7 +337,7 @@ public partial class SyncNextPlayoutHandler(
ChannelSubtitleMode subtitleMode, ChannelSubtitleMode subtitleMode,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
List<Subtitle> allSubtitles = await GetSubtitles(audioVersion.MediaItem); List<Subtitle> allSubtitles = await GetSubtitles(audioVersion.MediaItem, playoutItem.Id, playoutItem.InPoint);
Option<MediaStream> maybeAudioStream = Option<MediaStream>.None; Option<MediaStream> maybeAudioStream = Option<MediaStream>.None;
Option<Subtitle> maybeSubtitle = Option<Subtitle>.None; Option<Subtitle> maybeSubtitle = Option<Subtitle>.None;
@ -407,6 +409,21 @@ public partial class SyncNextPlayoutHandler(
}; };
} }
} }
else if (subtitle.Path.StartsWith("http://localhost", StringComparison.OrdinalIgnoreCase))
{
if (nextPlayoutItem.Tracks?.Subtitle?.Source is null)
{
nextPlayoutItem.Tracks ??= new Core.Next.PlayoutItemTracks();
nextPlayoutItem.Tracks.Subtitle ??= new Core.Next.TrackSelection();
nextPlayoutItem.Tracks.Subtitle.Source = new Core.Next.Source
{
SourceType = Core.Next.SourceType.Http,
Uri = subtitle.Path,
KeepAlive = false,
Reconnect = true
};
}
}
} }
} }
@ -672,7 +689,10 @@ public partial class SyncNextPlayoutHandler(
} }
} }
private static async Task<List<Subtitle>> GetSubtitles(MediaItem mediaItem) private static async Task<List<Subtitle>> GetSubtitles(
MediaItem mediaItem,
int playoutItemId,
TimeSpan playoutItemInPoint)
{ {
List<Subtitle> allSubtitles = mediaItem switch List<Subtitle> allSubtitles = mediaItem switch
{ {
@ -682,7 +702,7 @@ public partial class SyncNextPlayoutHandler(
Movie movie => await Optional(movie.MovieMetadata).Flatten().HeadOrNone() Movie movie => await Optional(movie.MovieMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles ?? []) .Map(mm => mm.Subtitles ?? [])
.IfNoneAsync([]), .IfNoneAsync([]),
//MusicVideo musicVideo => await GetMusicVideoSubtitles(musicVideo, channel, settings), MusicVideo => GetMusicVideoSubtitles(playoutItemId, playoutItemInPoint),
OtherVideo otherVideo => await Optional(otherVideo.OtherVideoMetadata).Flatten().HeadOrNone() OtherVideo otherVideo => await Optional(otherVideo.OtherVideoMetadata).Flatten().HeadOrNone()
.Map(mm => mm.Subtitles ?? []) .Map(mm => mm.Subtitles ?? [])
.IfNoneAsync([]), .IfNoneAsync([]),
@ -703,4 +723,25 @@ public partial class SyncNextPlayoutHandler(
return allSubtitles; return allSubtitles;
} }
private static List<Subtitle> GetMusicVideoSubtitles(int playoutItemId, TimeSpan playoutItemInPoint)
{
string seekToMs = playoutItemInPoint > TimeSpan.Zero
? $"?seekToMs={(long)playoutItemInPoint.TotalMilliseconds}"
: string.Empty;
return
[
new Subtitle
{
Codec = "ass",
Default = true,
Forced = true,
IsExtracted = false,
SubtitleKind = SubtitleKind.Generated,
Path = $"http://localhost:{Settings.StreamingPort}/ffmpeg/music-video-credits/{playoutItemId}{seekToMs}",
SDH = false
}
];
}
} }

7
ErsatzTV.Application/Streaming/Queries/GetMusicVideoCreditsByPlayoutItemIdHandler.cs

@ -60,9 +60,10 @@ public class GetMusicVideoCreditsByPlayoutItemIdHandler(
switch (playoutItem.Playout.Channel.MusicVideoCreditsMode) switch (playoutItem.Playout.Channel.MusicVideoCreditsMode)
{ {
case ChannelMusicVideoCreditsMode.GenerateSubtitles: case ChannelMusicVideoCreditsMode.GenerateSubtitles:
var fileWithExtension = $"{playoutItem.Playout.Channel.MusicVideoCreditsTemplate}.sbntxt"; string templateName = playoutItem.Playout.Channel.MusicVideoCreditsTemplate;
if (!string.IsNullOrWhiteSpace(fileWithExtension)) if (!string.IsNullOrWhiteSpace(templateName))
{ {
var fileWithExtension = $"{templateName}.sbntxt";
subtitles.AddRange( subtitles.AddRange(
await musicVideoCreditsGenerator.GenerateCreditsSubtitleFromTemplate( await musicVideoCreditsGenerator.GenerateCreditsSubtitleFromTemplate(
musicVideo, musicVideo,
@ -74,7 +75,7 @@ public class GetMusicVideoCreditsByPlayoutItemIdHandler(
{ {
logger.LogWarning( logger.LogWarning(
"Music video credits template {Template} does not exist; falling back to built-in template", "Music video credits template {Template} does not exist; falling back to built-in template",
fileWithExtension); templateName);
subtitles.AddRange( subtitles.AddRange(
await musicVideoCreditsGenerator.GenerateCreditsSubtitle( await musicVideoCreditsGenerator.GenerateCreditsSubtitle(

Loading…
Cancel
Save