HlsSegmentService.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using MediaBrowser.Controller;
  2. using MediaBrowser.Controller.Configuration;
  3. using MediaBrowser.Controller.Net;
  4. using System;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using MediaBrowser.Controller.MediaEncoding;
  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 IServerApplicationPaths _appPaths;
  76. private readonly IServerConfigurationManager _config;
  77. private readonly IFileSystem _fileSystem;
  78. public HlsSegmentService(IServerApplicationPaths appPaths, IServerConfigurationManager config, IFileSystem fileSystem)
  79. {
  80. _appPaths = appPaths;
  81. _config = config;
  82. _fileSystem = fileSystem;
  83. }
  84. public Task<object> Get(GetHlsPlaylistLegacy request)
  85. {
  86. var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
  87. file = Path.Combine(_appPaths.TranscodingTempPath, file);
  88. return GetFileResult(file, file);
  89. }
  90. public void Delete(StopEncodingProcess request)
  91. {
  92. ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, path => true);
  93. }
  94. /// <summary>
  95. /// Gets the specified request.
  96. /// </summary>
  97. /// <param name="request">The request.</param>
  98. /// <returns>System.Object.</returns>
  99. public Task<object> Get(GetHlsVideoSegmentLegacy request)
  100. {
  101. var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
  102. var transcodeFolderPath = _config.ApplicationPaths.TranscodingTempPath;
  103. file = Path.Combine(transcodeFolderPath, file);
  104. var normalizedPlaylistId = request.PlaylistId;
  105. var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath)
  106. .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
  107. return GetFileResult(file, playlistPath);
  108. }
  109. /// <summary>
  110. /// Gets the specified request.
  111. /// </summary>
  112. /// <param name="request">The request.</param>
  113. /// <returns>System.Object.</returns>
  114. public Task<object> Get(GetHlsAudioSegmentLegacy request)
  115. {
  116. // TODO: Deprecate with new iOS app
  117. var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
  118. file = Path.Combine(_appPaths.TranscodingTempPath, file);
  119. return ResultFactory.GetStaticFileResult(Request, file, FileShareMode.ReadWrite);
  120. }
  121. private Task<object> GetFileResult(string path, string playlistPath)
  122. {
  123. var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
  124. return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
  125. {
  126. Path = path,
  127. FileShare = FileShareMode.ReadWrite,
  128. OnComplete = () =>
  129. {
  130. if (transcodingJob != null)
  131. {
  132. ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob);
  133. }
  134. }
  135. });
  136. }
  137. }
  138. }