HlsSegmentService.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using MediaBrowser.Common.Configuration;
  6. using MediaBrowser.Controller.Configuration;
  7. using MediaBrowser.Controller.MediaEncoding;
  8. using MediaBrowser.Controller.Net;
  9. using MediaBrowser.Model.IO;
  10. using MediaBrowser.Model.Services;
  11. namespace MediaBrowser.Api.Playback.Hls
  12. {
  13. /// <summary>
  14. /// Class GetHlsAudioSegment
  15. /// </summary>
  16. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string
  17. //[Authenticated]
  18. [Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")]
  19. [Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")]
  20. public class GetHlsAudioSegmentLegacy
  21. {
  22. // TODO: Deprecate with new iOS app
  23. /// <summary>
  24. /// Gets or sets the id.
  25. /// </summary>
  26. /// <value>The id.</value>
  27. public string Id { get; set; }
  28. /// <summary>
  29. /// Gets or sets the segment id.
  30. /// </summary>
  31. /// <value>The segment id.</value>
  32. public string SegmentId { get; set; }
  33. }
  34. /// <summary>
  35. /// Class GetHlsVideoSegment
  36. /// </summary>
  37. [Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
  38. [Authenticated]
  39. public class GetHlsPlaylistLegacy
  40. {
  41. // TODO: Deprecate with new iOS app
  42. /// <summary>
  43. /// Gets or sets the id.
  44. /// </summary>
  45. /// <value>The id.</value>
  46. public string Id { get; set; }
  47. public string PlaylistId { get; set; }
  48. }
  49. [Route("/Videos/ActiveEncodings", "DELETE")]
  50. [Authenticated]
  51. public class StopEncodingProcess
  52. {
  53. [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")]
  54. public string DeviceId { get; set; }
  55. [ApiMember(Name = "PlaySessionId", Description = "The play session id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
  56. public string PlaySessionId { get; set; }
  57. }
  58. /// <summary>
  59. /// Class GetHlsVideoSegment
  60. /// </summary>
  61. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string
  62. //[Authenticated]
  63. [Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
  64. public class GetHlsVideoSegmentLegacy : VideoStreamRequest
  65. {
  66. public string PlaylistId { get; set; }
  67. /// <summary>
  68. /// Gets or sets the segment id.
  69. /// </summary>
  70. /// <value>The segment id.</value>
  71. public string SegmentId { get; set; }
  72. }
  73. public class HlsSegmentService : BaseApiService
  74. {
  75. private readonly IServerConfigurationManager _config;
  76. private readonly IFileSystem _fileSystem;
  77. public HlsSegmentService(IServerConfigurationManager config, IFileSystem fileSystem)
  78. {
  79. _config = config;
  80. _fileSystem = fileSystem;
  81. }
  82. public Task<object> Get(GetHlsPlaylistLegacy request)
  83. {
  84. var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
  85. file = Path.Combine(_config.GetTranscodePath(), file);
  86. return GetFileResult(file, file);
  87. }
  88. public Task Delete(StopEncodingProcess request)
  89. {
  90. return ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, path => true);
  91. }
  92. /// <summary>
  93. /// Gets the specified request.
  94. /// </summary>
  95. /// <param name="request">The request.</param>
  96. /// <returns>System.Object.</returns>
  97. public Task<object> Get(GetHlsVideoSegmentLegacy request)
  98. {
  99. var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
  100. var transcodeFolderPath = _config.GetTranscodePath();
  101. file = Path.Combine(transcodeFolderPath, file);
  102. var normalizedPlaylistId = request.PlaylistId;
  103. var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath)
  104. .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
  105. return GetFileResult(file, playlistPath);
  106. }
  107. /// <summary>
  108. /// Gets the specified request.
  109. /// </summary>
  110. /// <param name="request">The request.</param>
  111. /// <returns>System.Object.</returns>
  112. public Task<object> Get(GetHlsAudioSegmentLegacy request)
  113. {
  114. // TODO: Deprecate with new iOS app
  115. var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
  116. file = Path.Combine(_config.GetTranscodePath(), file);
  117. return ResultFactory.GetStaticFileResult(Request, file, FileShareMode.ReadWrite);
  118. }
  119. private Task<object> GetFileResult(string path, string playlistPath)
  120. {
  121. var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
  122. return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
  123. {
  124. Path = path,
  125. FileShare = FileShareMode.ReadWrite,
  126. OnComplete = () =>
  127. {
  128. if (transcodingJob != null)
  129. {
  130. ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob);
  131. }
  132. }
  133. });
  134. }
  135. }
  136. }