|
@@ -152,7 +152,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
RedirectStandardError = true,
|
|
|
FileName = FFProbePath,
|
|
|
Arguments = string.Format(args,
|
|
|
- probeSizeArgument, inputPath).Trim(),
|
|
|
+ probeSizeArgument, inputPath).Trim(),
|
|
|
|
|
|
WindowStyle = ProcessWindowStyle.Hidden,
|
|
|
ErrorDialog = false
|
|
@@ -186,8 +186,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
{
|
|
|
process.BeginErrorReadLine();
|
|
|
|
|
|
- result =
|
|
|
- _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
|
|
|
+ result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
|
|
|
}
|
|
|
catch
|
|
|
{
|
|
@@ -292,7 +291,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
// apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600.
|
|
|
// This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar
|
|
|
var vf = "scale=600:trunc(600/dar/2)*2";
|
|
|
- //crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,scale=600:(600/dar),thumbnail" -f image2
|
|
|
|
|
|
if (threedFormat.HasValue)
|
|
|
{
|
|
@@ -344,7 +342,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
WindowStyle = ProcessWindowStyle.Hidden,
|
|
|
ErrorDialog = false,
|
|
|
RedirectStandardOutput = true,
|
|
|
- RedirectStandardError = true
|
|
|
+ RedirectStandardError = true,
|
|
|
+ RedirectStandardInput = true
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -370,7 +369,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
{
|
|
|
_logger.Info("Killing ffmpeg process");
|
|
|
|
|
|
- process.Kill();
|
|
|
+ process.StandardInput.WriteLine("q");
|
|
|
|
|
|
process.WaitForExit(1000);
|
|
|
}
|
|
@@ -437,5 +436,93 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|
|
{
|
|
|
return time.ToString(@"hh\:mm\:ss\.fff", UsCulture);
|
|
|
}
|
|
|
+
|
|
|
+ public async Task ExtractVideoImagesOnInterval(string[] inputFiles,
|
|
|
+ MediaProtocol protocol,
|
|
|
+ Video3DFormat? threedFormat,
|
|
|
+ TimeSpan interval,
|
|
|
+ string targetDirectory,
|
|
|
+ string filenamePrefix,
|
|
|
+ int? maxWidth,
|
|
|
+ CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ var resourcePool = _videoImageResourcePool;
|
|
|
+
|
|
|
+ var inputArgument = GetInputArgument(inputFiles, protocol);
|
|
|
+
|
|
|
+ var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture);
|
|
|
+
|
|
|
+ if (maxWidth.HasValue)
|
|
|
+ {
|
|
|
+ var maxWidthParam = maxWidth.Value.ToString(UsCulture);
|
|
|
+
|
|
|
+ vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam);
|
|
|
+ }
|
|
|
+
|
|
|
+ Directory.CreateDirectory(targetDirectory);
|
|
|
+ var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg");
|
|
|
+
|
|
|
+ var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);
|
|
|
+
|
|
|
+ var probeSize = GetProbeSizeArgument(new[] { inputArgument }, protocol);
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(probeSize))
|
|
|
+ {
|
|
|
+ args = probeSize + " " + args;
|
|
|
+ }
|
|
|
+
|
|
|
+ var process = new Process
|
|
|
+ {
|
|
|
+ StartInfo = new ProcessStartInfo
|
|
|
+ {
|
|
|
+ CreateNoWindow = true,
|
|
|
+ UseShellExecute = false,
|
|
|
+ FileName = FFMpegPath,
|
|
|
+ Arguments = args,
|
|
|
+ WindowStyle = ProcessWindowStyle.Hidden,
|
|
|
+ ErrorDialog = false,
|
|
|
+ RedirectStandardInput = true
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
|
|
+
|
|
|
+ await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
|
+
|
|
|
+ process.Start();
|
|
|
+
|
|
|
+ var ranToCompletion = process.WaitForExit(120000);
|
|
|
+
|
|
|
+ if (!ranToCompletion)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _logger.Info("Killing ffmpeg process");
|
|
|
+
|
|
|
+ process.StandardInput.WriteLine("q");
|
|
|
+
|
|
|
+ process.WaitForExit(1000);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ _logger.ErrorException("Error killing process", ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ resourcePool.Release();
|
|
|
+
|
|
|
+ var exitCode = ranToCompletion ? process.ExitCode : -1;
|
|
|
+
|
|
|
+ process.Dispose();
|
|
|
+
|
|
|
+ if (exitCode == -1)
|
|
|
+ {
|
|
|
+ var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument);
|
|
|
+
|
|
|
+ _logger.Error(msg);
|
|
|
+
|
|
|
+ throw new ApplicationException(msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|