private async Task <object> GetAsync(GetMasterManifest request, string method) { if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Audio codec copy is not allowed here."); } if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Video codec copy is not allowed here."); } if (string.IsNullOrEmpty(request.MediaSourceId)) { throw new ArgumentException("MediaSourceId is required"); } var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); var playlistText = string.Empty; if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase)) { playlistText = GetManifestText(state); } return(ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.mpd"), new Dictionary <string, string>())); }
private string GetMimeType(ImageFormat format, string path) { if (format == ImageFormat.Bmp) { return(MimeTypes.GetMimeType("i.bmp")); } if (format == ImageFormat.Gif) { return(MimeTypes.GetMimeType("i.gif")); } if (format == ImageFormat.Jpg) { return(MimeTypes.GetMimeType("i.jpg")); } if (format == ImageFormat.Png) { return(MimeTypes.GetMimeType("i.png")); } if (format == ImageFormat.Webp) { return(MimeTypes.GetMimeType("i.webp")); } return(MimeTypes.GetMimeType(path)); }
public Task <object> GetStaticFileResult(IRequest requestContext, StaticFileResultOptions options) { var path = options.Path; var fileShare = options.FileShare; if (string.IsNullOrEmpty(path)) { throw new ArgumentException("Path can't be empty.", nameof(options)); } if (fileShare != FileShareMode.Read && fileShare != FileShareMode.ReadWrite) { throw new ArgumentException("FileShare must be either Read or ReadWrite"); } if (string.IsNullOrEmpty(options.ContentType)) { options.ContentType = MimeTypes.GetMimeType(path); } if (!options.DateLastModified.HasValue) { options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); } options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); return(GetStaticResult(requestContext, options)); }
public async Task <object> Get(GetSubtitle request) { if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase)) { request.Format = "json"; } if (string.IsNullOrEmpty(request.Format)) { var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null) .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id)); var subtitleStream = mediaSource.MediaStreams .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index); return(await ResultFactory.GetStaticFileResult(Request, subtitleStream.Path).ConfigureAwait(false)); } using (var stream = await GetSubtitles(request).ConfigureAwait(false)) { using (var reader = new StreamReader(stream)) { var text = reader.ReadToEnd(); if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap) { text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000"); } return(ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format))); } } }
public Task <object> GetStaticFileResult(IRequest requestContext, StaticFileResultOptions options) { var path = options.Path; var fileShare = options.FileShare; if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } if (fileShare != FileShare.Read && fileShare != FileShare.ReadWrite) { throw new ArgumentException("FileShare must be either Read or ReadWrite"); } if (string.IsNullOrWhiteSpace(options.ContentType)) { options.ContentType = MimeTypes.GetMimeType(path); } if (!options.DateLastModified.HasValue) { options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); } var cacheKey = path + options.DateLastModified.Value.Ticks; options.CacheKey = cacheKey.GetMD5(); options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); return(GetStaticResult(requestContext, options)); }
public async Task <object> Get(GetSubtitlePlaylist request) { var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.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(request.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(request.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("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(ResultFactory.GetResult(Request, builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
private async Task <object> GetVariantPlaylistInternal(StreamRequest request, bool isOutputVideo, string name) { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); var segmentLengths = GetSegmentLengths(state); var builder = new StringBuilder(); builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); builder.AppendLine("#EXT-X-VERSION:3"); builder.Append("#EXT-X-TARGETDURATION:") .AppendLine(Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture)); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); // if ((Request.UserAgent ?? string.Empty).IndexOf("roku", StringComparison.OrdinalIgnoreCase) != -1) //{ // queryString = string.Empty; //} var index = 0; foreach (var length in segmentLengths) { builder.Append("#EXTINF:") .Append(length.ToString("0.0000", CultureInfo.InvariantCulture)) .AppendLine(", nodesc"); builder.AppendFormat( CultureInfo.InvariantCulture, "hls1/{0}/{1}{2}{3}", name, index.ToString(CultureInfo.InvariantCulture), GetSegmentFileExtension(request), queryString).AppendLine(); index++; } builder.AppendLine("#EXT-X-ENDLIST"); var playlistText = builder.ToString(); return(ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
public object Get(GetSubtitlePlaylist request) { var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); var mediaSource = item.GetMediaSources(false) .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id)); var builder = new StringBuilder(); var runtime = mediaSource.RunTimeTicks ?? -1; if (runtime <= 0) { throw new ArgumentException("HLS Subtitles are not supported for this media."); } builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture)); builder.AppendLine("#EXT-X-VERSION:3"); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); long positionTicks = 0; var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks; while (positionTicks < runtime) { var remaining = runtime - positionTicks; var lengthTicks = Math.Min(remaining, segmentLengthTicks); builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture)); var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks); var url = string.Format("stream.srt?StartPositionTicks={0}&EndPositionTicks={1}", positionTicks.ToString(CultureInfo.InvariantCulture), endPositionTicks.ToString(CultureInfo.InvariantCulture)); builder.AppendLine(url); positionTicks += segmentLengthTicks; } builder.AppendLine("#EXT-X-ENDLIST"); return(ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
public Task <object> GetStaticFileResult(IRequest requestContext, StaticFileResultOptions options) { var path = options.Path; var fileShare = options.FileShare; if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } if (fileShare != FileShareMode.Read && fileShare != FileShareMode.ReadWrite) { throw new ArgumentException("FileShare must be either Read or ReadWrite"); } if (string.IsNullOrWhiteSpace(options.ContentType)) { options.ContentType = MimeTypes.GetMimeType(path); } if (!options.DateLastModified.HasValue) { options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); } var cacheKey = path + options.DateLastModified.Value.Ticks; options.CacheKey = cacheKey.GetMD5(); options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); if (!options.ResponseHeaders.ContainsKey("Content-Disposition")) { // Quotes are valid in linux. They'll possibly cause issues here var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty); if (!string.IsNullOrWhiteSpace(filename)) { options.ResponseHeaders["Content-Disposition"] = "inline; filename=\"" + filename + "\""; } } return(GetStaticResult(requestContext, options)); }
private async Task <object> GetPlaylistAsync(VideoStreamRequest request, string name) { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); var builder = new StringBuilder(); builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-VERSION:3"); builder.AppendLine("#EXT-X-TARGETDURATION:" + state.SegmentLength.ToString(UsCulture)); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); builder.AppendLine("#EXT-X-ALLOW-CACHE:NO"); var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds; var index = 0; while (seconds > 0) { var length = seconds >= state.SegmentLength ? state.SegmentLength : seconds; builder.AppendLine("#EXTINF:" + length.ToString(UsCulture) + ","); builder.AppendLine(string.Format("hlsdynamic/{0}/{1}.ts{2}", name, index.ToString(UsCulture), queryString)); seconds -= state.SegmentLength; index++; } builder.AppendLine("#EXT-X-ENDLIST"); var playlistText = builder.ToString(); return(ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
private async Task <object> GetMasterPlaylistInternal(StreamRequest request, string method) { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); if (string.IsNullOrEmpty(request.MediaSourceId)) { throw new ArgumentException("MediaSourceId is required"); } var playlistText = string.Empty; if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase)) { var audioBitrate = state.OutputAudioBitrate ?? 0; var videoBitrate = state.OutputVideoBitrate ?? 0; playlistText = GetMasterPlaylistFileText(state, videoBitrate + audioBitrate); } return(ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
private async Task <object> GetVariantPlaylistInternal(StreamRequest request, bool isOutputVideo, string name) { var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); var segmentLengths = GetSegmentLengths(state); var builder = new StringBuilder(); builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXT-X-VERSION:3"); builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling((segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength)).ToString(UsCulture)); builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0"); var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); var index = 0; foreach (var length in segmentLengths) { builder.AppendLine("#EXTINF:" + length.ToString("0.000000", UsCulture) + ","); builder.AppendLine(string.Format("hlsdynamic/{0}/{1}{2}{3}", name, index.ToString(UsCulture), GetSegmentFileExtension(isOutputVideo), queryString)); index++; } builder.AppendLine("#EXT-X-ENDLIST"); var playlistText = builder.ToString(); return(ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary <string, string>())); }
public object Get(GetSubtitle request) { if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase)) { request.Format = "json"; } if (string.IsNullOrEmpty(request.Format)) { var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null) .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id)); var subtitleStream = mediaSource.MediaStreams .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index); return(ToStaticFileResult(subtitleStream.Path)); } var stream = GetSubtitles(request).Result; return(ResultFactory.GetResult(stream, MimeTypes.GetMimeType("file." + request.Format))); }
public async Task <object> Get(GetRemoteSubtitles request) { var result = await _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).ConfigureAwait(false); return(ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format))); }
public object Get(GetRemoteSubtitles request) { var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result; return(ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format))); }