using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using ServiceStack; using System; using System.IO; using System.Linq; namespace MediaBrowser.Api.Playback.Hls { /// /// Class GetHlsAudioSegment /// [Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")] [Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")] [Api(Description = "Gets an Http live streaming segment file. Internal use only.")] public class GetHlsAudioSegment { /// /// Gets or sets the id. /// /// The id. public string Id { get; set; } /// /// Gets or sets the segment id. /// /// The segment id. public string SegmentId { get; set; } } /// /// Class GetHlsVideoSegment /// [Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")] [Api(Description = "Gets an Http live streaming segment file. Internal use only.")] public class GetHlsPlaylist { // TODO: Deprecate with new iOS app /// /// Gets or sets the id. /// /// The id. public string Id { get; set; } public string PlaylistId { get; set; } } [Route("/Videos/ActiveEncodings", "DELETE")] [Api(Description = "Stops an encoding process")] public class StopEncodingProcess { [ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] public string DeviceId { get; set; } [ApiMember(Name = "StreamId", Description = "The stream id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] public string StreamId { get; set; } } /// /// Class GetHlsVideoSegment /// [Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.ts", "GET")] [Api(Description = "Gets an Http live streaming segment file. Internal use only.")] public class GetHlsVideoSegment : VideoStreamRequest { public string PlaylistId { get; set; } /// /// Gets or sets the segment id. /// /// The segment id. public string SegmentId { get; set; } } public class HlsSegmentService : BaseApiService { private readonly IServerApplicationPaths _appPaths; private readonly IServerConfigurationManager _config; public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config) { _appPaths = appPaths; _config = config; } public object Get(GetHlsPlaylist request) { var file = request.PlaylistId + Path.GetExtension(Request.PathInfo); file = Path.Combine(_appPaths.TranscodingTempPath, file); return GetFileResult(file, file); } public void Delete(StopEncodingProcess request) { ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.StreamId, path => true); } /// /// Gets the specified request. /// /// The request. /// System.Object. public object Get(GetHlsVideoSegment request) { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file); var normalizedPlaylistId = request.PlaylistId.Replace("-low", string.Empty); var playlistPath = Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*") .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); return GetFileResult(file, playlistPath); } /// /// Gets the specified request. /// /// The request. /// System.Object. public object Get(GetHlsAudioSegment request) { // TODO: Deprecate with new iOS app var file = request.SegmentId + Path.GetExtension(Request.PathInfo); file = Path.Combine(_appPaths.TranscodingTempPath, file); return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite); } private object GetFileResult(string path, string playlistPath) { var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls); return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions { Path = path, FileShare = FileShare.ReadWrite, OnComplete = () => { if (transcodingJob != null) { ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob); } } }); } } }