diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 882eaae698..178bec2b68 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -647,11 +647,14 @@ namespace MediaBrowser.Api.Playback videoRequest.VideoCodec = InferVideoCodec(url); } - state.AudioStream = GetMediaStream(media.MediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio, true); state.VideoStream = GetMediaStream(media.MediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video, true); state.SubtitleStream = GetMediaStream(media.MediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false); } - + else + { + state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true); + } + return state; } diff --git a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs index a98f274998..ecdab94b3c 100644 --- a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs @@ -2,10 +2,32 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; +using ServiceStack.ServiceHost; using System; +using System.IO; namespace MediaBrowser.Api.Playback.Hls { + /// + /// Class GetHlsAudioStream + /// + [Route("/Audio/{Id}/stream.m3u8", "GET")] + [ServiceStack.ServiceHost.Api(Description = "Gets an audio stream using HTTP live streaming.")] + public class GetHlsAudioStream : StreamRequest + { + + } + + [Route("/Audio/{Id}/segments/{SegmentId}.mp3", "GET")] + [Route("/Audio/{Id}/segments/{SegmentId}.aac", "GET")] + [ServiceStack.ServiceHost.Api(Description = "Gets an Http live streaming segment file. Internal use only.")] + public class GetHlsAudioSegment + { + public string Id { get; set; } + + public string SegmentId { get; set; } + } + /// /// Class AudioHlsService /// @@ -16,6 +38,25 @@ namespace MediaBrowser.Api.Playback.Hls { } + public object Get(GetHlsAudioSegment request) + { + var file = SegmentFilePrefix + request.SegmentId + Path.GetExtension(Request.PathInfo); + + file = Path.Combine(ApplicationPaths.EncodedMediaCachePath, file); + + return ToStaticFileResult(file); + } + + /// + /// Gets the specified request. + /// + /// The request. + /// System.Object. + public object Get(GetHlsAudioStream request) + { + return ProcessRequest(request); + } + /// /// Gets the audio arguments. /// @@ -75,7 +116,7 @@ namespace MediaBrowser.Api.Playback.Hls return ".mp3"; } - throw new InvalidOperationException("Only aac and mp3 audio codecs are supported."); + throw new ArgumentException("Must specify either aac or mp3 audio codec."); } /// diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 6a303a03e2..43d98307fa 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -52,10 +52,11 @@ namespace MediaBrowser.Api.Playback.Hls /// /// Processes the request. /// - /// The state. /// System.Object. - protected object ProcessRequest(StreamState state) + protected object ProcessRequest(StreamRequest request) { + var state = GetState(request); + return ProcessRequestAsync(state).Result; } @@ -85,12 +86,10 @@ namespace MediaBrowser.Api.Playback.Hls var content = Encoding.UTF8.GetBytes(playlistText); - var stream = new MemoryStream(content); - try { Response.ContentType = MimeTypes.GetMimeType("playlist.m3u8"); - return new StreamWriter(stream); + return content; } finally { @@ -130,6 +129,8 @@ namespace MediaBrowser.Api.Playback.Hls // The segement paths within the playlist are phsyical, so strip that out to make it relative fileText = fileText.Replace(Path.GetDirectoryName(playlist) + Path.DirectorySeparatorChar, string.Empty); + fileText = fileText.Replace(SegmentFilePrefix, "segments/"); + // Even though we specify target duration of 9, ffmpeg seems unable to keep all segments under that amount fileText = fileText.Replace("#EXT-X-TARGETDURATION:9", "#EXT-X-TARGETDURATION:10");