public async Task <MediaSourceInfo> GetMediaSource(CancellationToken cancellationToken) { if (mediaSource != null) { return(mediaSource); } var hasMediaSources = Item as IHasMediaSources; if (hasMediaSources == null) { return(null); } if (_mediaSourceManager != null) { mediaSource = await _mediaSourceManager.GetMediaSource(Item, MediaSourceId, LiveStreamId, false, cancellationToken).ConfigureAwait(false); } return(mediaSource); }
public async Task <ActionResult> GetSubtitlePlaylist( [FromRoute, Required] Guid itemId, [FromRoute, Required] int index, [FromRoute, Required] string?mediaSourceId, [FromQuery, Required] int segmentLength) { var item = (Video)_libraryManager.GetItemById(itemId); var mediaSource = await _mediaSourceManager.GetMediaSource(item, mediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false); var runtime = mediaSource.RunTimeTicks ?? -1; if (runtime <= 0) { throw new ArgumentException("HLS Subtitles are not supported for this media."); } var segmentLengthTicks = TimeSpan.FromSeconds(segmentLength).Ticks; if (segmentLengthTicks <= 0) { throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)"); } var builder = new StringBuilder(); builder.AppendLine("#EXTM3U") .Append("#EXT-X-TARGETDURATION:") .AppendLine(segmentLength.ToString(CultureInfo.InvariantCulture)) .AppendLine("#EXT-X-VERSION:3") .AppendLine("#EXT-X-MEDIA-SEQUENCE:0") .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); long positionTicks = 0; var accessToken = _authContext.GetAuthorizationInfo(Request).Token; while (positionTicks < runtime) { var remaining = runtime - positionTicks; var lengthTicks = Math.Min(remaining, segmentLengthTicks); builder.Append("#EXTINF:") .Append(TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture)) .AppendLine(","); var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks); var url = string.Format( CultureInfo.CurrentCulture, "stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}", positionTicks.ToString(CultureInfo.InvariantCulture), endPositionTicks.ToString(CultureInfo.InvariantCulture), accessToken); builder.AppendLine(url); positionTicks += segmentLengthTicks; } builder.AppendLine("#EXT-X-ENDLIST"); return(File(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8"))); }
public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager) { var request = new StreamParams { ItemId = GetItemId(url) }; Guid parsedId; if (string.IsNullOrWhiteSpace(request.ItemId) || !Guid.TryParse(request.ItemId, out parsedId)) { return(request); } const string srch = "params="; var index = url.IndexOf(srch, StringComparison.OrdinalIgnoreCase); if (index == -1) { return(request); } var vals = url.Substring(index + srch.Length).Split(';'); for (var i = 0; i < vals.Length; i++) { var val = vals[i]; if (string.IsNullOrWhiteSpace(val)) { continue; } if (i == 0) { request.DeviceProfileId = val; } else if (i == 1) { request.DeviceId = val; } else if (i == 2) { request.MediaSourceId = val; } else if (i == 3) { request.IsDirectStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } else if (i == 6) { request.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture); } else if (i == 7) { request.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture); } else if (i == 14) { request.StartPositionTicks = long.Parse(val, CultureInfo.InvariantCulture); } } request.Item = string.IsNullOrWhiteSpace(request.ItemId) ? null : libraryManager.GetItemById(parsedId); var hasMediaSources = request.Item as IHasMediaSources; request.MediaSource = hasMediaSources == null ? null : mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, false).Result; return(request); }