public static Task <Stream> ProcessAsync(IOwinContext context, WebMediaType mediatype, WebFileType filetype, string id, int offset) { ISet <Guid> necessaryMIATypes = new HashSet <Guid>(); necessaryMIATypes.Add(MediaAspect.ASPECT_ID); necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID); necessaryMIATypes.Add(ImporterAspect.ASPECT_ID); MediaItem item = MediaLibraryAccess.GetMediaItemById(context, id, necessaryMIATypes, null); if (item == null) { throw new NotFoundException("RetrieveFile: no media item found"); } var files = ResourceAccessUtils.GetResourcePaths(item); var ra = GetResourceAccessor(files[offset]); IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor; if (fsra == null) { throw new InternalServerException("RetrieveFile: failed to create IFileSystemResourceAccessor"); } return(fsra.OpenReadAsync()); }
internal static WebTVSeasonBasic TVSeasonBasic(IOwinContext context, MediaItem item, Guid?showId = null) { Guid? user = ResourceAccessUtils.GetUser(context); ISet <Guid> necessaryMIATypespisodes = new HashSet <Guid>(); necessaryMIATypespisodes.Add(MediaAspect.ASPECT_ID); necessaryMIATypespisodes.Add(EpisodeAspect.ASPECT_ID); IFilter unwatchedEpisodeFilter = BooleanCombinationFilter.CombineFilters(BooleanOperator.And, new RelationshipFilter(EpisodeAspect.ROLE_EPISODE, SeasonAspect.ROLE_SEASON, item.MediaItemId), new RelationalUserDataFilter(user.Value, UserDataKeysKnown.KEY_PLAY_PERCENTAGE, RelationalOperator.LT, UserDataKeysKnown.GetSortablePlayPercentageString(100), true)); int unwatchedCount = MediaLibraryAccess.CountMediaItems(context, necessaryMIATypespisodes, unwatchedEpisodeFilter); GetShowId(item, ref showId); var mediaAspect = item.GetAspect(MediaAspect.Metadata); var seasonAspect = item.GetAspect(SeasonAspect.Metadata); var importerAspect = item.GetAspect(ImporterAspect.Metadata); DateTime?firstAired = mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_RECORDINGTIME); return(new WebTVSeasonBasic { Title = mediaAspect.GetAttributeValue <string>(MediaAspect.ATTR_TITLE), Id = item.MediaItemId.ToString(), ShowId = showId.HasValue ? showId.Value.ToString() : null, SeasonNumber = seasonAspect.GetAttributeValue <int>(SeasonAspect.ATTR_SEASON), EpisodeCount = seasonAspect.GetAttributeValue <int>(SeasonAspect.ATTR_AVAILABLE_EPISODES), UnwatchedEpisodeCount = unwatchedCount, DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), Year = firstAired.HasValue ? firstAired.Value.Year : 0, }); }
public static Task <IList <string> > ProcessAsync(IOwinContext context, WebMediaType mediatype, WebFileType filetype, string id) { if (id == null) { throw new BadRequestException("GetPathList: id is null"); } ISet <Guid> necessaryMIATypes = new HashSet <Guid>(); necessaryMIATypes.Add(MediaAspect.ASPECT_ID); necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID); necessaryMIATypes.Add(ImporterAspect.ASPECT_ID); ISet <Guid> optionalMIATypes = new HashSet <Guid>(); optionalMIATypes.Add(VideoAspect.ASPECT_ID); optionalMIATypes.Add(MovieAspect.ASPECT_ID); optionalMIATypes.Add(SeriesAspect.ASPECT_ID); optionalMIATypes.Add(AudioAspect.ASPECT_ID); optionalMIATypes.Add(ImageAspect.ASPECT_ID); MediaItem item = MediaLibraryAccess.GetMediaItemById(context, Guid.Parse(id), necessaryMIATypes, optionalMIATypes); if (item == null) { throw new NotFoundException(String.Format("GetPathList: No MediaItem found with id: {0}", id)); } var output = ResourceAccessUtils.GetPaths(item); return(System.Threading.Tasks.Task.FromResult(output)); }
public static async Task <WebStringResult> ProcessAsync(IOwinContext context, string identifier, string profileName, long startPosition) { if (identifier == null) { throw new BadRequestException("InitStream: identifier is null"); } if (profileName == null) { throw new BadRequestException("InitStream: profileName is null"); } StreamItem streamItem = await StreamControl.GetStreamItemAsync(identifier); if (streamItem == null) { throw new BadRequestException(string.Format("StartStream: Unknown identifier: {0}", identifier)); } // Prefer getting profile by name EndPointProfile profile = ProfileManager.Profiles.Values.FirstOrDefault(p => p.Name == profileName); // If no ptofile with the specified name, see if there's one with a matching id if (profile == null && !ProfileManager.Profiles.TryGetValue(profileName, out profile)) { throw new BadRequestException(string.Format("StartStream: Unknown profile: {0}", profileName)); } streamItem.Profile = profile; // Seeking is not supported in live streams streamItem.StartPosition = streamItem.RequestedMediaItem is LiveTvMediaItem ? 0 : startPosition; Guid?userId = ResourceAccessUtils.GetUser(context); streamItem.TranscoderObject = new ProfileMediaItem(identifier, profile, streamItem.IsLive); await streamItem.TranscoderObject.Initialize(userId, streamItem.RequestedMediaItem, null); if (streamItem.TranscoderObject.TranscodingParameter is VideoTranscoding vt) { vt.HlsBaseUrl = string.Format("RetrieveStream?identifier={0}&hls=", identifier); } await StreamControl.StartStreamingAsync(identifier, startPosition); string filePostFix = "&file=media.ts"; if (profile.MediaTranscoding?.VideoTargets?.Any(t => t.Target.VideoContainerType == VideoContainer.Hls) ?? false) { filePostFix = "&file=manifest.m3u8"; //Must be added for some clients to work (Android mostly) } string url = GetBaseStreamUrl.GetBaseStreamURL(context) + "/MPExtended/StreamingService/stream/RetrieveStream?identifier=" + identifier + filePostFix; return(new WebStringResult { Result = url }); }
internal static WebMovieBasic MovieBasic(MediaItem item) { MediaItemAspect movieAspect = item.GetAspect(MovieAspect.Metadata); MediaItemAspect videoAspect = item.GetAspect(VideoAspect.Metadata); MediaItemAspect mediaAspect = item.GetAspect(MediaAspect.Metadata); MediaItemAspect importerAspect = item.GetAspect(ImporterAspect.Metadata); WebMovieBasic webMovieBasic = new WebMovieBasic { Title = movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_MOVIE_NAME), Id = item.MediaItemId.ToString(), Type = WebMediaType.Movie, Path = ResourceAccessUtils.GetPaths(item), Year = mediaAspect.GetAttributeValue <DateTime>(MediaAspect.ATTR_RECORDINGTIME).Year, Runtime = movieAspect.GetAttributeValue <int>(MovieAspect.ATTR_RUNTIME_M), Watched = Convert.ToInt32(item.UserData.FirstOrDefault(d => d.Key == UserDataKeysKnown.KEY_PLAY_PERCENTAGE).Value ?? "0") >= 100, DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), Rating = Convert.ToSingle(movieAspect.GetAttributeValue <double>(MovieAspect.ATTR_TOTAL_RATING)), Artwork = ResourceAccessUtils.GetWebArtwork(item), }; IEnumerable <string> aspectActors = videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS); if (aspectActors != null) { webMovieBasic.Actors = aspectActors.Distinct().Select(a => new WebActor(a)).ToList(); } IList <MediaItemAspect> genres; if (item.Aspects.TryGetValue(GenreAspect.ASPECT_ID, out genres)) { webMovieBasic.Genres = genres.Select(g => g.GetAttributeValue <string>(GenreAspect.ATTR_GENRE)).ToList(); } string tmdbId; if (MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_MOVIE, out tmdbId) && tmdbId != null) { webMovieBasic.ExternalId.Add(new WebExternalId { Site = "TMDB", Id = tmdbId }); } string imdbId; if (MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, out imdbId) && imdbId != null) { webMovieBasic.ExternalId.Add(new WebExternalId { Site = "IMDB", Id = imdbId }); } return(webMovieBasic); }
internal static WebMusicTrackBasic MusicTrackBasic(MediaItem item) { MediaItemAspect audioAspect = item.GetAspect(AudioAspect.Metadata); MediaItemAspect mediaAspect = item.GetAspect(MediaAspect.Metadata); MediaItemAspect importerAspect = item.GetAspect(ImporterAspect.Metadata); WebMusicTrackBasic webTrackBasic = new WebMusicTrackBasic { Title = audioAspect.GetAttributeValue <string>(AudioAspect.ATTR_TRACKNAME), Id = item.MediaItemId.ToString(), Type = WebMediaType.MusicTrack, Path = ResourceAccessUtils.GetPaths(item), Year = mediaAspect.GetAttributeValue <DateTime>(MediaAspect.ATTR_RECORDINGTIME).Year, Duration = (int)audioAspect.GetAttributeValue <long>(AudioAspect.ATTR_DURATION), DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), Rating = Convert.ToSingle(audioAspect.GetAttributeValue <double>(AudioAspect.ATTR_TOTAL_RATING)), Artwork = ResourceAccessUtils.GetWebArtwork(item), Album = audioAspect.GetAttributeValue <string>(AudioAspect.ATTR_ALBUM), DiscNumber = audioAspect.GetAttributeValue <int>(AudioAspect.ATTR_DISCID), TrackNumber = audioAspect.GetAttributeValue <int>(AudioAspect.ATTR_TRACK), }; IEnumerable <string> aspectArtists = audioAspect.GetCollectionAttribute <string>(AudioAspect.ATTR_ARTISTS); if (aspectArtists != null) { webTrackBasic.Artist = aspectArtists.Distinct().ToList(); } aspectArtists = audioAspect.GetCollectionAttribute <string>(AudioAspect.ATTR_ALBUMARTISTS); if (aspectArtists != null) { webTrackBasic.AlbumArtist = aspectArtists.FirstOrDefault(); } if (MediaItemAspect.TryGetAspects(item.Aspects, RelationshipAspect.Metadata, out var relationAspects)) { webTrackBasic.ArtistId = relationAspects.Where(r => (Guid?)r[RelationshipAspect.ATTR_LINKED_ROLE] == PersonAspect.ROLE_ARTIST).Select(r => r[RelationshipAspect.ATTR_LINKED_ID].ToString()).ToList(); webTrackBasic.AlbumId = relationAspects.Where(r => (Guid?)r[RelationshipAspect.ATTR_LINKED_ROLE] == AudioAlbumAspect.ROLE_ALBUM).Select(r => r[RelationshipAspect.ATTR_LINKED_ID].ToString()).FirstOrDefault(); webTrackBasic.AlbumArtistId = relationAspects.Where(r => (Guid?)r[RelationshipAspect.ATTR_LINKED_ROLE] == PersonAspect.ROLE_ALBUMARTIST).Select(r => r[RelationshipAspect.ATTR_LINKED_ID].ToString()).FirstOrDefault(); } IList <MediaItemAspect> genres; if (item.Aspects.TryGetValue(GenreAspect.ASPECT_ID, out genres)) { webTrackBasic.Genres = genres.Select(g => g.GetAttributeValue <string>(GenreAspect.ATTR_GENRE)).ToList(); } return(webTrackBasic); }
internal static WebTVEpisodeBasic EpisodeBasic(MediaItem item, Guid?showId = null, Guid?seasonId = null) { MediaItemAspect episodeAspect = item.GetAspect(EpisodeAspect.Metadata); MediaItemAspect importerAspect = item.GetAspect(ImporterAspect.Metadata); MediaItemAspect mediaAspect = item.GetAspect(MediaAspect.Metadata); IEnumerable <int> episodeNumbers = episodeAspect.GetCollectionAttribute <int>(EpisodeAspect.ATTR_EPISODE); int episodeNumber = episodeNumbers != null?episodeNumbers.FirstOrDefault() : 0; GetParentIds(item, ref showId, ref seasonId); WebTVEpisodeBasic webTvEpisodeBasic = new WebTVEpisodeBasic { Title = episodeAspect.GetAttributeValue <string>(EpisodeAspect.ATTR_EPISODE_NAME), EpisodeNumber = episodeNumber, Id = item.MediaItemId.ToString(), ShowId = showId.HasValue ? showId.Value.ToString() : null, SeasonId = seasonId.HasValue ? seasonId.Value.ToString() : null, Type = WebMediaType.TVEpisode, Path = ResourceAccessUtils.GetPaths(item), Watched = Convert.ToInt32(item.UserData.FirstOrDefault(d => d.Key == UserDataKeysKnown.KEY_PLAY_PERCENTAGE).Value ?? "0") >= 100, DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), SeasonNumber = episodeAspect.GetAttributeValue <int>(EpisodeAspect.ATTR_SEASON), FirstAired = mediaAspect.GetAttributeValue <DateTime>(MediaAspect.ATTR_RECORDINGTIME), Rating = Convert.ToSingle(episodeAspect.GetAttributeValue <double>(EpisodeAspect.ATTR_TOTAL_RATING)), Artwork = ResourceAccessUtils.GetWebArtwork(item), }; string TvDbId; MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_TVDB, ExternalIdentifierAspect.TYPE_SERIES, out TvDbId); if (TvDbId != null) { webTvEpisodeBasic.ExternalId.Add(new WebExternalId { Site = "TVDB", Id = TvDbId }); } string ImdbId; MediaItemAspect.TryGetExternalAttribute(item.Aspects, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_SERIES, out ImdbId); if (ImdbId != null) { webTvEpisodeBasic.ExternalId.Add(new WebExternalId { Site = "IMDB", Id = ImdbId }); } return(webTvEpisodeBasic); }
internal static WebMusicArtistBasic MusicArtistBasic(MediaItem item) { MediaItemAspect artistAspect = item.GetAspect(PersonAspect.Metadata); bool hasAlbum = false; if (MediaItemAspect.TryGetAspects(item.Aspects, RelationshipAspect.Metadata, out var relationAspects)) { hasAlbum = relationAspects.Any(r => (Guid?)r[RelationshipAspect.ATTR_LINKED_ROLE] == AudioAlbumAspect.ROLE_ALBUM); } return(new WebMusicArtistBasic { HasAlbums = hasAlbum, Id = item.MediaItemId.ToString(), Title = artistAspect.GetAttributeValue <string>(PersonAspect.ATTR_PERSON_NAME), Artwork = ResourceAccessUtils.GetWebArtwork(item) }); }
public static Task <WebFileInfo> ProcessAsync(IOwinContext context, WebMediaType mediatype, WebFileType filetype, string id, int offset) { ISet <Guid> necessaryMIATypes = new HashSet <Guid>(); necessaryMIATypes.Add(MediaAspect.ASPECT_ID); necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID); necessaryMIATypes.Add(ImporterAspect.ASPECT_ID); MediaItem item = MediaLibraryAccess.GetMediaItemById(context, id, necessaryMIATypes, null); if (item == null) { throw new NotFoundException("GetFileInfo: no media item found"); } var files = ResourceAccessUtils.GetResourcePaths(item); var ra = GetResourceAccessor(files[offset]); IFileSystemResourceAccessor fsra = ra as IFileSystemResourceAccessor; if (fsra == null) { throw new InternalServerException("GetFileInfo: failed to create IFileSystemResourceAccessor"); } WebFileInfo webFileInfo = new WebFileInfo { Exists = fsra.Exists, Extension = fsra.Path.Split('.').Last(), IsLocalFile = true, IsReadOnly = true, LastAccessTime = DateTime.Now, LastModifiedTime = fsra.LastChanged, Name = fsra.ResourceName, OnNetworkDrive = false, Path = files[offset].FileName, Size = fsra.Size, }; return(Task.FromResult(webFileInfo)); }
public static Task <WebMediaItem> ProcessAsync(IOwinContext context, string id) { if (id == null) { throw new BadRequestException("GetMediaItem: id is null"); } ISet <Guid> necessaryMIATypes = new HashSet <Guid>(); necessaryMIATypes.Add(MediaAspect.ASPECT_ID); necessaryMIATypes.Add(ProviderResourceAspect.ASPECT_ID); necessaryMIATypes.Add(ImporterAspect.ASPECT_ID); ISet <Guid> optionalMIATypes = new HashSet <Guid>(); optionalMIATypes.Add(VideoAspect.ASPECT_ID); optionalMIATypes.Add(MovieAspect.ASPECT_ID); optionalMIATypes.Add(EpisodeAspect.ASPECT_ID); optionalMIATypes.Add(AudioAspect.ASPECT_ID); optionalMIATypes.Add(ImageAspect.ASPECT_ID); MediaItem item = MediaLibraryAccess.GetMediaItemById(context, Guid.Parse(id), necessaryMIATypes, optionalMIATypes); if (item == null) { throw new NotFoundException(String.Format("GetMediaItem: No MediaItem found with id: {0}", id)); } WebMediaItem webMediaItem = new WebMediaItem(); webMediaItem.Id = item.MediaItemId.ToString(); webMediaItem.Artwork = ResourceAccessUtils.GetWebArtwork(item); webMediaItem.DateAdded = item.GetAspect(ImporterAspect.Metadata).GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED); webMediaItem.Path = ResourceAccessUtils.GetPaths(item); webMediaItem.Type = ResourceAccessUtils.GetWebMediaType(item); webMediaItem.Title = item.GetAspect(MediaAspect.Metadata).GetAttributeValue <string>(MediaAspect.ATTR_TITLE); return(Task.FromResult(webMediaItem)); }
internal static WebMusicAlbumBasic MusicAlbumBasic(MediaItem item) { MediaItemAspect importerAspect = item.GetAspect(ImporterAspect.Metadata); MediaItemAspect mediaAspect = item.GetAspect(MediaAspect.Metadata); MediaItemAspect albumAspect = item.GetAspect(AudioAlbumAspect.Metadata); var artists = albumAspect.GetCollectionAttribute <string>(AudioAlbumAspect.ATTR_ARTISTS); IList <MultipleMediaItemAspect> genres; if (!MediaItemAspect.TryGetAspects(item.Aspects, GenreAspect.Metadata, out genres)) { genres = new List <MultipleMediaItemAspect>(); } var artistIds = new HashSet <string>(); if (MediaItemAspect.TryGetAspects(item.Aspects, RelationshipAspect.Metadata, out var relationAspects)) { artistIds = new HashSet <string>(relationAspects.Where(r => (Guid?)r[RelationshipAspect.ATTR_LINKED_ROLE] == PersonAspect.ROLE_ALBUMARTIST).Select(r => r[RelationshipAspect.ATTR_LINKED_ID].ToString())); } return(new WebMusicAlbumBasic { Id = item.MediaItemId.ToString(), Artists = artists?.ToList(), ArtistsId = artistIds?.ToList(), AlbumArtist = artists?.FirstOrDefault()?.ToString(), AlbumArtistId = artistIds?.FirstOrDefault()?.ToString(), Genres = genres?.Select(a => a.GetAttributeValue <string>(GenreAspect.ATTR_GENRE)).ToList(), Title = albumAspect.GetAttributeValue <string>(AudioAlbumAspect.ATTR_ALBUM), Year = mediaAspect.GetAttributeValue <DateTime>(MediaAspect.ATTR_RECORDINGTIME).Year, DateAdded = importerAspect.GetAttributeValue <DateTime>(ImporterAspect.ATTR_DATEADDED), Rating = Convert.ToSingle(albumAspect.GetAttributeValue <double>(AudioAlbumAspect.ATTR_TOTAL_RATING)), Artwork = ResourceAccessUtils.GetWebArtwork(item), //Composer = composers.Cast<string>().ToList() }); }
internal static WebRecordingBasic RecordingBasic(MediaItem item) { MediaItemAspect recordingAspect = item.GetAspect(RecordingAspect.Metadata); string genre = string.Empty; if (MediaItemAspect.TryGetAttribute(item.Aspects, GenreAspect.ATTR_GENRE, out List <string> genres)) { genre = string.Join(", ", genres); } return(new WebRecordingBasic { Id = item.MediaItemId.ToString(), Title = (string)item.GetAspect(MediaAspect.Metadata).GetAttributeValue(MediaAspect.ATTR_TITLE), ChannelName = (string)recordingAspect.GetAttributeValue(RecordingAspect.ATTR_CHANNEL), Description = (string)item.GetAspect(VideoAspect.Metadata).GetAttributeValue(VideoAspect.ATTR_STORYPLOT), StartTime = (DateTime)(recordingAspect.GetAttributeValue(RecordingAspect.ATTR_STARTTIME) ?? DateTime.Now), EndTime = (DateTime)(recordingAspect.GetAttributeValue(RecordingAspect.ATTR_ENDTIME) ?? DateTime.Now), Genre = genre, TimesWatched = Convert.ToInt32(item.UserData.FirstOrDefault(d => d.Key == UserDataKeysKnown.KEY_PLAY_COUNT).Value ?? "0"), FileName = ResourceAccessUtils.GetPaths(item).FirstOrDefault(), }); }
internal static WebPictureBasic PictureBasic(MediaItem item) { MediaItemAspect imageAspects = item.GetAspect(ImageAspect.Metadata); WebPictureBasic webPictureBasic = new WebPictureBasic { Type = WebMediaType.Picture, DateAdded = (DateTime)item.GetAspect(ImporterAspect.Metadata).GetAttributeValue(ImporterAspect.ATTR_DATEADDED), Id = item.MediaItemId.ToString(), Title = (string)item.GetAspect(MediaAspect.Metadata).GetAttributeValue(MediaAspect.ATTR_TITLE), DateTaken = (DateTime)item.GetAspect(MediaAspect.Metadata)[MediaAspect.ATTR_RECORDINGTIME], Path = ResourceAccessUtils.GetPaths(item), Artwork = ResourceAccessUtils.GetWebArtwork(item), }; webPictureBasic.Categories = new[] { new WebCategory { Title = (webPictureBasic.DateTaken).ToString("yyyy"), Id = (webPictureBasic.DateTaken).ToString("yyyy") } }; return(webPictureBasic); }
internal static Guid StringToGuid(string value) { byte[] bytes = ResourceAccessUtils.GetBytes(value); return(new Guid(bytes)); }
public async Task Initialize(Guid?userId, MediaItem item, int?edition, int?audioId = null, int?subtitleId = null) { MediaItemId = item.MediaItemId; var info = await MediaAnalyzer.ParseMediaItemAsync(item); if (info == null) { Logger.Warn("MP2Extended: Mediaitem {0} couldn't be analyzed", item.MediaItemId); return; } int? audioStreamId = null; List <string> preferredAudioLang = new List <string>(); List <string> preferredSubtitleLang = new List <string>(); await ResourceAccessUtils.AddPreferredLanguagesAsync(userId, preferredAudioLang, preferredSubtitleLang); if (audioId.HasValue) { if (audioId.Value >= EDITION_OFFSET) { edition = (audioId.Value / EDITION_OFFSET) - 1; audioStreamId = audioId.Value - ((audioId.Value / EDITION_OFFSET) * EDITION_OFFSET); } else { audioStreamId = audioId; } } if (item.HasEditions && !edition.HasValue) { //Find edition with best matching audio that doesn't require transcoding int currentPriority = -1; bool currentRequiresTranscoding = false; foreach (var checkEdition in info.Metadata.Keys) { for (int idx = 0; idx < info.Audio[checkEdition].Count; idx++) { VideoTranscoding video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, checkEdition, preferredAudioLang, IsLive, ""); bool requiresTranscoding = video != null; for (int priority = 0; priority < preferredAudioLang.Count; priority++) { if (preferredAudioLang[priority].Equals(info.Audio[checkEdition][idx].Language, StringComparison.InvariantCultureIgnoreCase) == true) { if (currentPriority == -1 || priority < currentPriority || (!requiresTranscoding && currentRequiresTranscoding && priority == currentPriority)) { currentPriority = priority; currentRequiresTranscoding = requiresTranscoding; audioStreamId = info.Audio[checkEdition][idx].StreamIndex; _edition = checkEdition; } } } } } } else { //Assign first edition _edition = info.Metadata.Min(m => m.Key); } if (item.Aspects.ContainsKey(AudioAspect.ASPECT_ID)) { IsAudio = true; } else if (item.Aspects.ContainsKey(ImageAspect.ASPECT_ID)) { IsImage = true; } else if (item.Aspects.ContainsKey(VideoAspect.ASPECT_ID)) { IsVideo = true; } else { Logger.Warn("MP2Extended: Mediaitem {0} contains no required aspect information", item.MediaItemId); return; } string transcodeId = item.MediaItemId.ToString() + "_" + Profile.ID; if (IsLive) { transcodeId = Guid.NewGuid().ToString() + "_" + Profile.ID; } if (MP2Extended.Settings.TranscodingAllowed) { if (IsAudio) { AudioTranscoding audio = TranscodeProfileManager.GetAudioTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, _edition, IsLive, transcodeId); TranscodingParameter = audio; } else if (IsImage) { ImageTranscoding image = TranscodeProfileManager.GetImageTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, _edition, transcodeId); TranscodingParameter = image; } else if (IsVideo) { VideoTranscoding video; if (audioStreamId.HasValue) { video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, _edition, audioStreamId.Value, subtitleId, IsLive, transcodeId); } else { video = TranscodeProfileManager.GetVideoTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, _edition, preferredAudioLang, IsLive, transcodeId); } if (video != null) { if (video.TargetVideoContainer == VideoContainer.Hls) { IsSegmented = true; } if (MP2Extended.Settings.HardcodedSubtitlesAllowed == false) { video.TargetSubtitleSupport = SubtitleSupport.None; } } TranscodingParameter = video; } } if (TranscodingParameter == null) { if (IsLive) { if (IsVideo) { if (audioStreamId.HasValue) { TranscodingParameter = TranscodeProfileManager.GetLiveVideoTranscoding(info, audioStreamId.Value, transcodeId); } else { TranscodingParameter = TranscodeProfileManager.GetLiveVideoTranscoding(info, preferredAudioLang, transcodeId); } } else if (IsAudio) { TranscodingParameter = TranscodeProfileManager.GetLiveAudioTranscoding(info, transcodeId); } } else if (IsVideo) { VideoTranscoding video = TranscodeProfileManager.GetVideoSubtitleTranscoding(ProfileManager.TRANSCODE_PROFILE_SECTION, Profile.ID, info, _edition, IsLive, transcodeId); if (video != null) { if (video.TargetVideoContainer == VideoContainer.Hls) { IsSegmented = true; } if (MP2Extended.Settings.HardcodedSubtitlesAllowed == false) { video.TargetSubtitleSupport = SubtitleSupport.None; } } TranscodingParameter = video; } } AssignWebMetadata(info, _edition); }
protected static async Task SendAsync(IOwinContext context, Stream resourceStream, ProfileMediaItem item, EndPointProfile profile, bool onlyHeaders, bool partialResource, Range byteRange) { if (onlyHeaders) { return; } bool clientDisconnected = false; Guid streamID = item.StartStreaming(); if (streamID == Guid.Empty) { Logger.Error("BaseSendData: Unable to start stream"); return; } try { if (context.Response.ContentLength == 0) { //Not allowed to have a content length of zero context.Response.ContentLength = null; } Logger.Debug("BaseSendData: Sending chunked: {0}", context.Response.ContentLength == null); string clientID = context.Request.RemoteIpAddress; int bufferSize = profile.Settings.Communication.DefaultBufferSize; if (bufferSize <= 0) { bufferSize = 1500; } byte[] buffer = new byte[bufferSize]; int bytesRead; long count = 0; bool isStream = false; long waitForSize = 0; if (byteRange.Length == 0 || (byteRange.Length > 0 && byteRange.Length >= profile.Settings.Communication.InitialBufferSize)) { waitForSize = profile.Settings.Communication.InitialBufferSize; } if (partialResource == false) { if (waitForSize < byteRange.From) { waitForSize = byteRange.From; } } if (await WaitForMinimumFileSizeAsync(resourceStream, waitForSize) == false) { Logger.Error("BaseSendData: Unable to send stream because of invalid length: {0} ({1} required)", resourceStream.Length, waitForSize); return; } long start = 0; if (partialResource == false) { start = byteRange.From; } if (resourceStream.CanSeek) { resourceStream.Seek(start, SeekOrigin.Begin); } long length = byteRange.Length; if (length <= 0 || item.IsLive || (item.IsSegmented == false && item.IsTranscoding == true)) { isStream = true; } int emptyCount = 0; while (item.IsStreamActive(streamID)) { if (isStream) { if (resourceStream.CanSeek) { length = resourceStream.Length - count; } else { length = bufferSize; //Keep stream alive } } bytesRead = await resourceStream.ReadAsync(buffer, 0, length > bufferSize?bufferSize : (int)length); count += bytesRead; if (bytesRead > 0) { emptyCount = 0; try { //Send fetched bytes await context.Response.WriteAsync(buffer, 0, bytesRead, SendDataCancellation.Token); } catch (Exception) { // Client disconnected Logger.Debug("BaseSendData: Connection lost after {0} bytes", count); clientDisconnected = true; break; } length -= bytesRead; if (isStream == false && length <= 0) { //All bytes in the requested range sent break; } } else { emptyCount++; if (emptyCount > 2) { Logger.Debug("BaseSendData: Buffer underrun delay"); await Task.Delay(100); } if (emptyCount > 10) { //Stream is not getting any bigger break; } } if (resourceStream.CanSeek) { if (item.IsTranscoding == false && resourceStream.Position == resourceStream.Length) { //No more data will be available break; } } } } finally { item.StopStreaming(streamID); if (clientDisconnected || item.IsSegmented == false) { if (clientDisconnected == false) { //Everything sent to client so presume watched if (item.IsLive == false) { Guid? userId = ResourceAccessUtils.GetUser(context); IMediaLibrary library = ServiceRegistration.Get <IMediaLibrary>(); if (library != null && userId.HasValue) { library.NotifyUserPlayback(userId.Value, item.MediaItemId, 100, true); } } } } Logger.Debug("BaseSendData: Sending complete"); } }
public static async Task <WebStringResult> ProcessAsync(IOwinContext context, string identifier, string profileName, long startPosition, int audioId = -1, int subtitleId = -1) { if (identifier == null) { throw new BadRequestException("StartStreamWithStreamSelection: identifier is null"); } if (profileName == null) { throw new BadRequestException("StartStreamWithStreamSelection: profileName is null"); } EndPointProfile profile = null; List <EndPointProfile> namedProfiles = ProfileManager.Profiles.Where(x => x.Value.Name == profileName).Select(namedProfile => namedProfile.Value).ToList(); if (namedProfiles.Count > 0) { profile = namedProfiles[0]; } else if (ProfileManager.Profiles.ContainsKey(profileName)) { profile = ProfileManager.Profiles[profileName]; } if (profile == null) { throw new BadRequestException(string.Format("StartStreamWithStreamSelection: unknown profile: {0}", profileName)); } StreamItem streamItem = await StreamControl.GetStreamItemAsync(identifier); if (streamItem == null) { throw new BadRequestException(string.Format("StartStreamWithStreamSelection: unknown identifier: {0}", identifier)); } streamItem.Profile = profile; streamItem.StartPosition = startPosition; if (streamItem.RequestedMediaItem is LiveTvMediaItem) { streamItem.StartPosition = 0; } Guid?userId = ResourceAccessUtils.GetUser(context); streamItem.TranscoderObject = new ProfileMediaItem(identifier, profile, streamItem.IsLive); await streamItem.TranscoderObject.Initialize(userId, streamItem.RequestedMediaItem, audioId >= 0?audioId : (int?)null, subtitleId); if ((streamItem.TranscoderObject.TranscodingParameter is VideoTranscoding vt)) { vt.HlsBaseUrl = string.Format("RetrieveStream?identifier={0}&hls=", identifier); } await StreamControl.StartStreamingAsync(identifier, startPosition); string filePostFix = "&file=media.ts"; if (profile.MediaTranscoding != null && profile.MediaTranscoding.VideoTargets != null) { foreach (var target in profile.MediaTranscoding.VideoTargets) { if (target.Target.VideoContainerType == VideoContainer.Hls) { filePostFix = "&file=manifest.m3u8"; //Must be added for some clients to work (Android mostly) break; } } } string url = GetBaseStreamUrl.GetBaseStreamURL(context) + "/MPExtended/StreamingService/stream/RetrieveStream?identifier=" + identifier + filePostFix; return(new WebStringResult { Result = url }); }
public static Task <IList <WebArtwork> > ProcessAsync(IOwinContext context, WebMediaType type, string id) { var output = ResourceAccessUtils.GetWebArtwork(type, Guid.Parse(id)); return(System.Threading.Tasks.Task.FromResult <IList <WebArtwork> >(output)); }