using MediaBrowser.Common.IO; using MediaBrowser.Common.MediaInfo; 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")] [Api(Description = "Gets an audio stream using HTTP live streaming.")] public class GetHlsAudioStream : StreamRequest { } /// /// Class GetHlsAudioSegment /// [Route("/Audio/{Id}/segments/{SegmentId}/stream.mp3", "GET")] [Route("/Audio/{Id}/segments/{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 AudioHlsService /// public class AudioHlsService : BaseHlsService { /// /// Initializes a new instance of the class. /// /// The app paths. /// The user manager. /// The library manager. /// The iso manager. /// The media encoder. public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder) : base(appPaths, userManager, libraryManager, isoManager, mediaEncoder) { } /// /// Gets the specified request. /// /// The request. /// System.Object. public object Get(GetHlsAudioSegment request) { var file = SegmentFilePrefix + request.SegmentId + Path.GetExtension(RequestContext.PathInfo); file = Path.Combine(ApplicationPaths.EncodedMediaCachePath, file); return ResultFactory.GetStaticFileResult(RequestContext, file); } /// /// Gets the specified request. /// /// The request. /// System.Object. public object Get(GetHlsAudioStream request) { return ProcessRequest(request); } /// /// Gets the audio arguments. /// /// The state. /// System.String. protected override string GetAudioArguments(StreamState state) { var codec = GetAudioCodec(state.Request); var args = "-codec:a " + codec; if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase)) { args += " -strict experimental"; } var channels = GetNumAudioChannelsParam(state.Request, state.AudioStream); if (channels.HasValue) { args += " -ac " + channels.Value; } if (state.Request.AudioSampleRate.HasValue) { args += " -ar " + state.Request.AudioSampleRate.Value; } if (state.Request.AudioBitRate.HasValue) { args += " -ab " + state.Request.AudioBitRate.Value; } return args; } /// /// Gets the video arguments. /// /// The state. /// if set to true [perform subtitle conversion]. /// System.String. protected override string GetVideoArguments(StreamState state, bool performSubtitleConversion) { // No video return string.Empty; } /// /// Gets the segment file extension. /// /// The state. /// System.String. /// Must specify either aac or mp3 audio codec. /// Only aac and mp3 audio codecs are supported. protected override string GetSegmentFileExtension(StreamState state) { if (state.Request.AudioCodec == AudioCodecs.Aac) { return ".aac"; } if (state.Request.AudioCodec == AudioCodecs.Mp3) { return ".mp3"; } throw new ArgumentException("Must specify either aac or mp3 audio codec."); } /// /// Gets the map args. /// /// The state. /// System.String. protected override string GetMapArgs(StreamState state) { return string.Format("-map 0:{0}", state.AudioStream.Index); } } }