Switched FFProbe caching to use service stack's jsv serializer

pull/702/head
LukePulverenti Luke Pulverenti luke pulverenti 12 years ago
parent a3f08b02ca
commit b15c064bba

@ -13,48 +13,61 @@ namespace MediaBrowser.Controller.FFMpeg
/// </summary> /// </summary>
public static class FFProbe public static class FFProbe
{ {
public async static Task<FFProbeResult> Run(Audio item, string outputCachePath) public static FFProbeResult Run(Audio item)
{ {
// Use try catch to avoid having to use File.Exists // Use try catch to avoid having to use File.Exists
try try
{ {
return GetCachedResult(outputCachePath); return GetCachedResult(GetFFProbeAudioCachePath(item));
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
} }
await Run(item.Path, outputCachePath).ConfigureAwait(false); FFProbeResult result = Run(item.Path);
return GetCachedResult(item.Path); // Fire and forget
CacheResult(result, GetFFProbeAudioCachePath(item));
return result;
} }
public static FFProbeResult GetCachedResult(string path) private static FFProbeResult GetCachedResult(string path)
{ {
using (FileStream stream = File.OpenRead(path)) return JsvSerializer.DeserializeFromFile<FFProbeResult>(path);
}
private static void CacheResult(FFProbeResult result, string outputCachePath)
{
Task.Run(() =>
{ {
return JsonSerializer.DeserializeFromStream<FFProbeResult>(stream); JsvSerializer.SerializeToFile<FFProbeResult>(result, outputCachePath);
} });
} }
public async static Task<FFProbeResult> Run(Video item, string outputCachePath) public static FFProbeResult Run(Video item)
{ {
// Use try catch to avoid having to use File.Exists // Use try catch to avoid having to use File.Exists
try try
{ {
return GetCachedResult(outputCachePath); return GetCachedResult(GetFFProbeVideoCachePath(item));
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
} }
await Run(item.Path, outputCachePath).ConfigureAwait(false); FFProbeResult result = Run(item.Path);
return GetCachedResult(item.Path); // Fire and forget
CacheResult(result, GetFFProbeVideoCachePath(item));
return result;
} }
private async static Task Run(string input, string output) private static FFProbeResult Run(string input)
{ {
MediaBrowser.Common.Logging.Logger.LogInfo(input);
ProcessStartInfo startInfo = new ProcessStartInfo(); ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true; startInfo.CreateNoWindow = true;
@ -74,8 +87,6 @@ namespace MediaBrowser.Controller.FFMpeg
Process process = new Process(); Process process = new Process();
process.StartInfo = startInfo; process.StartInfo = startInfo;
FileStream stream = new FileStream(output, FileMode.Create);
try try
{ {
process.Start(); process.Start();
@ -84,23 +95,21 @@ namespace MediaBrowser.Controller.FFMpeg
// If we ever decide to disable the ffmpeg log then you must uncomment the below line. // If we ever decide to disable the ffmpeg log then you must uncomment the below line.
process.BeginErrorReadLine(); process.BeginErrorReadLine();
await process.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false); FFProbeResult result = JsonSerializer.DeserializeFromStream<FFProbeResult>(process.StandardOutput.BaseStream);
process.WaitForExit(); process.WaitForExit();
stream.Dispose();
if (process.ExitCode != 0) if (process.ExitCode != 0)
{ {
Logger.LogInfo("FFProbe exited with code {0} for {1}", process.ExitCode, input); Logger.LogInfo("FFProbe exited with code {0} for {1}", process.ExitCode, input);
} }
return result;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogException(ex); Logger.LogException(ex);
stream.Dispose();
// Hate having to do this // Hate having to do this
try try
{ {
@ -109,12 +118,27 @@ namespace MediaBrowser.Controller.FFMpeg
catch catch
{ {
} }
File.Delete(output);
return null;
} }
finally finally
{ {
process.Dispose(); process.Dispose();
} }
} }
private static string GetFFProbeAudioCachePath(BaseEntity item)
{
string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1));
return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".jsv");
}
private static string GetFFProbeVideoCachePath(BaseEntity item)
{
string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1));
return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".jsv");
}
} }
} }

@ -23,18 +23,14 @@ namespace MediaBrowser.Controller.Providers
get { return MetadataProviderPriority.First; } get { return MetadataProviderPriority.First; }
} }
public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) public override async Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
{ {
Audio audio = item as Audio; await Task.Run(() =>
{
Fetch(audio, await FFProbe.Run(audio, GetFFProbeOutputPath(item)).ConfigureAwait(false)); Audio audio = item as Audio;
}
private string GetFFProbeOutputPath(BaseEntity item)
{
string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1));
return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js"); Fetch(audio, FFProbe.Run(audio));
});
} }
private void Fetch(Audio audio, FFProbeResult data) private void Fetch(Audio audio, FFProbeResult data)

@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events;
using MediaBrowser.Controller.FFMpeg; using MediaBrowser.Controller.FFMpeg;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Providers namespace MediaBrowser.Controller.Providers
{ {
@ -27,27 +26,23 @@ namespace MediaBrowser.Controller.Providers
public override async Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) public override async Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
{ {
Video video = item as Video; await Task.Run(() =>
if (video.VideoType != VideoType.VideoFile)
{ {
// Not supported yet Video video = item as Video;
return;
}
if (CanSkip(video))
{
return;
}
Fetch(video, await FFProbe.Run(video, GetFFProbeOutputPath(video)).ConfigureAwait(false)); if (video.VideoType != VideoType.VideoFile)
} {
// Not supported yet
return;
}
private string GetFFProbeOutputPath(Video item) if (CanSkip(video))
{ {
string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1)); return;
}
return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js"); Fetch(video, FFProbe.Run(video));
});
} }
private void Fetch(Video video, FFProbeResult data) private void Fetch(Video video, FFProbeResult data)

Loading…
Cancel
Save