Stream custom live channels using your own media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

109 lines
4.3 KiB

using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Emby;
using ErsatzTV.Core.Interfaces.Jellyfin;
using ErsatzTV.Core.Interfaces.Plex;
namespace ErsatzTV.Core.Extensions;
public static class MediaItemExtensions
{
extension(MediaItem mediaItem)
{
public Option<TimeSpan> GetNonZeroDuration()
{
Option<TimeSpan> maybeDuration = mediaItem switch
{
Movie m => m.MediaVersions.HeadOrNone().Map(v => v.Duration),
Episode e => e.MediaVersions.HeadOrNone().Map(v => v.Duration),
MusicVideo mv => mv.MediaVersions.HeadOrNone().Map(v => v.Duration),
OtherVideo ov => ov.MediaVersions.HeadOrNone().Map(v => v.Duration),
Song s => s.MediaVersions.HeadOrNone().Map(v => v.Duration),
ChapterMediaItem c => c.MediaVersion.Duration,
_ => None
};
// zero duration is invalid, so return none in that case
return maybeDuration.Any(duration => duration == TimeSpan.Zero) ? Option<TimeSpan>.None : maybeDuration;
}
public TimeSpan GetDurationForPlayout()
{
if (mediaItem is Image image)
{
return TimeSpan.FromSeconds(image.ImageMetadata.Head().DurationSeconds ?? Image.DefaultSeconds);
}
MediaVersion version = mediaItem.GetHeadVersion();
if (mediaItem is RemoteStream remoteStream)
{
return version.Duration == TimeSpan.Zero && remoteStream.Duration.HasValue
? remoteStream.Duration.Value
: version.Duration;
}
return version.Duration;
}
public MediaVersion GetHeadVersion() =>
mediaItem switch
{
Movie m => m.MediaVersions.Head(),
Episode e => e.MediaVersions.Head(),
MusicVideo mv => mv.MediaVersions.Head(),
OtherVideo ov => ov.MediaVersions.Head(),
Song s => s.MediaVersions.Head(),
Image i => i.MediaVersions.Head(),
RemoteStream rs => rs.MediaVersions.Head(),
ChapterMediaItem c => c.MediaVersion,
_ => throw new ArgumentOutOfRangeException(nameof(mediaItem))
};
public async Task<string> GetLocalPath(
IPlexPathReplacementService plexPathReplacementService,
IJellyfinPathReplacementService jellyfinPathReplacementService,
IEmbyPathReplacementService embyPathReplacementService,
CancellationToken cancellationToken,
bool log = true)
{
MediaVersion version = mediaItem.GetHeadVersion();
MediaFile file = version.MediaFiles.Head();
string path = file.Path;
return mediaItem switch
{
PlexMovie plexMovie => await plexPathReplacementService.GetReplacementPlexPath(
plexMovie.LibraryPathId,
path,
cancellationToken,
log),
PlexEpisode plexEpisode => await plexPathReplacementService.GetReplacementPlexPath(
plexEpisode.LibraryPathId,
path,
cancellationToken,
log),
JellyfinMovie jellyfinMovie => await jellyfinPathReplacementService.GetReplacementJellyfinPath(
jellyfinMovie.LibraryPathId,
path,
cancellationToken,
log),
JellyfinEpisode jellyfinEpisode => await jellyfinPathReplacementService.GetReplacementJellyfinPath(
jellyfinEpisode.LibraryPathId,
path,
cancellationToken,
log),
EmbyMovie embyMovie => await embyPathReplacementService.GetReplacementEmbyPath(
embyMovie.LibraryPathId,
path,
cancellationToken,
log),
EmbyEpisode embyEpisode => await embyPathReplacementService.GetReplacementEmbyPath(
embyEpisode.LibraryPathId,
path,
cancellationToken,
log),
_ => path
};
}
}
}