diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs
index 852c4e7db6..c14705be67 100644
--- a/MediaBrowser.Api/ApiService.cs
+++ b/MediaBrowser.Api/ApiService.cs
@@ -13,45 +13,6 @@ namespace MediaBrowser.Api
///
public static class ApiService
{
- private static string _FFMpegDirectory = null;
- ///
- /// Gets the folder path to ffmpeg
- ///
- public static string FFMpegDirectory
- {
- get
- {
- if (_FFMpegDirectory == null)
- {
- _FFMpegDirectory = System.IO.Path.Combine(ApplicationPaths.ProgramDataPath, "ffmpeg");
-
- if (!Directory.Exists(_FFMpegDirectory))
- {
- Directory.CreateDirectory(_FFMpegDirectory);
-
- // Extract ffmpeg
- using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Api.ffmpeg.ffmpeg.exe"))
- {
- using (FileStream fileStream = new FileStream(FFMpegPath, FileMode.Create))
- {
- stream.CopyTo(fileStream);
- }
- }
- }
- }
-
- return _FFMpegDirectory;
- }
- }
-
- public static string FFMpegPath
- {
- get
- {
- return System.IO.Path.Combine(FFMpegDirectory, "ffmpeg.exe");
- }
- }
-
public static BaseItem GetItemById(string id)
{
Guid guid = string.IsNullOrEmpty(id) ? Guid.Empty : new Guid(id);
@@ -138,5 +99,58 @@ namespace MediaBrowser.Api
return null;
}
+
+ private static string _FFMpegDirectory = null;
+ ///
+ /// Gets the folder path to ffmpeg
+ ///
+ public static string FFMpegDirectory
+ {
+ get
+ {
+ if (_FFMpegDirectory == null)
+ {
+ _FFMpegDirectory = System.IO.Path.Combine(ApplicationPaths.ProgramDataPath, "ffmpeg");
+
+ if (!Directory.Exists(_FFMpegDirectory))
+ {
+ Directory.CreateDirectory(_FFMpegDirectory);
+ }
+ }
+
+ return _FFMpegDirectory;
+ }
+ }
+
+ private static string _FFMpegPath = null;
+ ///
+ /// Gets the path to ffmpeg.exe
+ ///
+ public static string FFMpegPath
+ {
+ get
+ {
+ if (_FFMpegPath == null)
+ {
+ string filename = "ffmpeg.exe";
+
+ _FFMpegPath = Path.Combine(FFMpegDirectory, filename);
+
+ if (!File.Exists(_FFMpegPath))
+ {
+ // Extract ffprobe
+ using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Api.FFMpeg." + filename))
+ {
+ using (FileStream fileStream = new FileStream(_FFMpegPath, FileMode.Create))
+ {
+ stream.CopyTo(fileStream);
+ }
+ }
+ }
+ }
+
+ return _FFMpegPath;
+ }
+ }
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/AudioHandler.cs b/MediaBrowser.Api/HttpHandlers/AudioHandler.cs
index f3839a8922..294a5b7afc 100644
--- a/MediaBrowser.Api/HttpHandlers/AudioHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/AudioHandler.cs
@@ -105,7 +105,7 @@ namespace MediaBrowser.Api.HttpHandlers
///
/// Creates arguments to pass to ffmpeg
///
- private string GetAudioArguments()
+ protected override string GetCommandLineArguments()
{
List audioTranscodeParams = new List();
@@ -132,40 +132,6 @@ namespace MediaBrowser.Api.HttpHandlers
return "-i \"" + LibraryItem.Path + "\" -vn " + string.Join(" ", audioTranscodeParams.ToArray()) + " -";
}
-
- protected async override Task WriteResponseToOutputStream(Stream stream)
- {
- ProcessStartInfo startInfo = new ProcessStartInfo();
-
- startInfo.CreateNoWindow = true;
-
- startInfo.UseShellExecute = false;
- startInfo.RedirectStandardOutput = true;
-
- startInfo.FileName = ApiService.FFMpegPath;
- startInfo.WorkingDirectory = ApiService.FFMpegDirectory;
- startInfo.Arguments = GetAudioArguments();
-
- Logger.LogInfo(startInfo.FileName + " " + startInfo.Arguments);
-
- Process process = new Process();
- process.StartInfo = startInfo;
-
- try
- {
- process.Start();
-
- await process.StandardOutput.BaseStream.CopyToAsync(stream);
- }
- catch (Exception ex)
- {
- Logger.LogException(ex);
- }
- finally
- {
- process.Dispose();
- }
- }
}
public abstract class BaseMediaHandler : BaseHandler
@@ -252,7 +218,48 @@ namespace MediaBrowser.Api.HttpHandlers
base.ProcessRequest(ctx);
}
+ protected abstract string GetCommandLineArguments();
protected abstract string GetOutputFormat();
protected abstract bool RequiresConversion();
+
+ protected async override Task WriteResponseToOutputStream(Stream stream)
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo();
+
+ startInfo.CreateNoWindow = true;
+
+ startInfo.UseShellExecute = false;
+ startInfo.RedirectStandardOutput = true;
+ startInfo.RedirectStandardError = true;
+
+ startInfo.FileName = ApiService.FFMpegPath;
+ startInfo.WorkingDirectory = ApiService.FFMpegDirectory;
+ startInfo.Arguments = GetCommandLineArguments();
+
+ Logger.LogInfo(startInfo.FileName + " " + startInfo.Arguments);
+
+ Process process = new Process();
+ process.StartInfo = startInfo;
+
+ try
+ {
+ process.Start();
+
+ // MUST read both stdout and stderr asynchronously or a deadlock may occurr
+ process.BeginErrorReadLine();
+
+ await process.StandardOutput.BaseStream.CopyToAsync(stream);
+
+ process.WaitForExit();
+ }
+ catch (Exception ex)
+ {
+ Logger.LogException(ex);
+ }
+ finally
+ {
+ process.Dispose();
+ }
+ }
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs
index f94b8fc311..1b5c50c38a 100644
--- a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs
@@ -1,20 +1,14 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
using System.Linq;
-using System.Net;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Logging;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Net.Handlers;
-using MediaBrowser.Controller;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Api.HttpHandlers
{
class VideoHandler : BaseMediaHandler