VideoService.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using MediaBrowser.Controller;
  2. using MediaBrowser.Controller.Entities;
  3. using MediaBrowser.Model.Logging;
  4. using System;
  5. namespace MediaBrowser.Api.Playback.Progressive
  6. {
  7. /// <summary>
  8. /// Class VideoService
  9. /// </summary>
  10. public class VideoService : BaseProgressiveStreamingService
  11. {
  12. /// <summary>
  13. /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
  14. /// </summary>
  15. /// <param name="appPaths">The app paths.</param>
  16. public VideoService(IServerApplicationPaths appPaths)
  17. : base(appPaths)
  18. {
  19. }
  20. /// <summary>
  21. /// Gets the command line arguments.
  22. /// </summary>
  23. /// <param name="outputPath">The output path.</param>
  24. /// <param name="state">The state.</param>
  25. /// <returns>System.String.</returns>
  26. protected override string GetCommandLineArguments(string outputPath, StreamState state)
  27. {
  28. var video = (Video)state.Item;
  29. var probeSize = ServerKernel.FFMpegManager.GetProbeSizeArgument(video.VideoType, video.IsoType);
  30. // Get the output codec name
  31. var videoCodec = GetVideoCodec(state.Request);
  32. var graphicalSubtitleParam = string.Empty;
  33. if (state.SubtitleStream != null)
  34. {
  35. // This is for internal graphical subs
  36. if (!state.SubtitleStream.IsExternal && (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1))
  37. {
  38. graphicalSubtitleParam = GetInternalGraphicalSubtitleParam(state, videoCodec);
  39. }
  40. }
  41. return string.Format("{0} {1} -i {2}{3} -threads 0 {4} {5}{6} {7} \"{8}\"",
  42. probeSize,
  43. GetFastSeekCommandLineParameter(state.Request),
  44. GetInputArgument(video, state.IsoMount),
  45. GetSlowSeekCommandLineParameter(state.Request),
  46. GetMapArgs(state),
  47. GetVideoArguments(state, videoCodec),
  48. graphicalSubtitleParam,
  49. GetAudioArguments(state),
  50. outputPath
  51. ).Trim();
  52. }
  53. /// <summary>
  54. /// Gets video arguments to pass to ffmpeg
  55. /// </summary>
  56. /// <param name="state">The state.</param>
  57. /// <param name="videoCodec">The video codec.</param>
  58. /// <returns>System.String.</returns>
  59. private string GetVideoArguments(StreamState state, string videoCodec)
  60. {
  61. var args = "-vcodec " + videoCodec;
  62. var request = state.Request;
  63. // If we're encoding video, add additional params
  64. if (!videoCodec.Equals("copy", StringComparison.OrdinalIgnoreCase))
  65. {
  66. // Add resolution params, if specified
  67. if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
  68. {
  69. args += GetOutputSizeParam(state, videoCodec);
  70. }
  71. if (request.Framerate.HasValue)
  72. {
  73. args += string.Format(" -r {0}", request.Framerate.Value);
  74. }
  75. // Add the audio bitrate
  76. var qualityParam = GetVideoQualityParam(request, videoCodec);
  77. if (!string.IsNullOrEmpty(qualityParam))
  78. {
  79. args += " " + qualityParam;
  80. }
  81. }
  82. else if (IsH264(state.VideoStream))
  83. {
  84. args += " -bsf h264_mp4toannexb";
  85. }
  86. return args;
  87. }
  88. /// <summary>
  89. /// Gets audio arguments to pass to ffmpeg
  90. /// </summary>
  91. /// <param name="state">The state.</param>
  92. /// <returns>System.String.</returns>
  93. private string GetAudioArguments(StreamState state)
  94. {
  95. // If the video doesn't have an audio stream, return a default.
  96. if (state.AudioStream == null)
  97. {
  98. return string.Empty;
  99. }
  100. var request = state.Request;
  101. // Get the output codec name
  102. var codec = GetAudioCodec(request);
  103. var args = "-acodec " + codec;
  104. // If we're encoding audio, add additional params
  105. if (!codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
  106. {
  107. // Add the number of audio channels
  108. var channels = GetNumAudioChannelsParam(request, state.AudioStream);
  109. if (channels.HasValue)
  110. {
  111. args += " -ac " + channels.Value;
  112. }
  113. if (request.AudioSampleRate.HasValue)
  114. {
  115. args += " -ar " + request.AudioSampleRate.Value;
  116. }
  117. if (request.AudioBitRate.HasValue)
  118. {
  119. args += " -ab " + request.AudioBitRate.Value;
  120. }
  121. }
  122. return args;
  123. }
  124. /// <summary>
  125. /// Gets the video bitrate to specify on the command line
  126. /// </summary>
  127. /// <param name="request">The request.</param>
  128. /// <param name="videoCodec">The video codec.</param>
  129. /// <returns>System.String.</returns>
  130. private string GetVideoQualityParam(StreamRequest request, string videoCodec)
  131. {
  132. var args = string.Empty;
  133. // webm
  134. if (videoCodec.Equals("libvpx", StringComparison.OrdinalIgnoreCase))
  135. {
  136. args = "-g 120 -cpu-used 1 -lag-in-frames 16 -deadline realtime -slices 4 -vprofile 0";
  137. }
  138. // asf/wmv
  139. else if (videoCodec.Equals("wmv2", StringComparison.OrdinalIgnoreCase))
  140. {
  141. args = "-g 100 -qmax 15";
  142. }
  143. else if (videoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase))
  144. {
  145. args = "-preset superfast";
  146. }
  147. if (request.VideoBitRate.HasValue)
  148. {
  149. args += " -b:v " + request.VideoBitRate;
  150. }
  151. return args.Trim();
  152. }
  153. }
  154. }