feat: add ffmpeg support for video analysis and screenshots
This commit is contained in:
parent
aa5c6d3f6d
commit
2bbbc32322
87
src/CasaBot/CasaBotApp/FFMPEGWrapper.cs
Normal file
87
src/CasaBot/CasaBotApp/FFMPEGWrapper.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CasaBotApp;
|
||||||
|
|
||||||
|
public class FfmpegWrapper
|
||||||
|
{
|
||||||
|
private readonly ILogger<FfmpegWrapper> _logger;
|
||||||
|
|
||||||
|
public FfmpegWrapper(ILogger<FfmpegWrapper> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string FFMPEG_PATH = @".\dvr-scanner\ffmpeg.exe";
|
||||||
|
//Include method for get duration of a video, extract the frame at a specific time
|
||||||
|
|
||||||
|
public async Task<TimeSpan> GetVideoDuration(string videoPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogDebug("Getting video duration...");
|
||||||
|
var ffmpegProcess = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = FFMPEG_PATH,
|
||||||
|
Arguments = $"-i {videoPath}",
|
||||||
|
RedirectStandardOutput = false,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardError = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ffmpegProcess.Start();
|
||||||
|
|
||||||
|
var standardError = await ffmpegProcess.StandardError.ReadToEndAsync();
|
||||||
|
await ffmpegProcess.WaitForExitAsync();
|
||||||
|
|
||||||
|
// Parse the duration from the ffmpeg output
|
||||||
|
var durationString = System.Text.RegularExpressions.Regex.Match(standardError, @"Duration: (\d{2}):(\d{2}):(\d{2})\.(\d{2})").Groups;
|
||||||
|
var ts = new TimeSpan(0,
|
||||||
|
int.Parse(durationString[1].Value),
|
||||||
|
int.Parse(durationString[2].Value),
|
||||||
|
int.Parse(durationString[3].Value),
|
||||||
|
int.Parse(durationString[4].Value) * 10
|
||||||
|
);
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "An error occurred while getting the video duration");
|
||||||
|
throw new Exception("There was an error getting the video duration", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExtractFrame(string videoPath, string outputPath, TimeSpan time)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var timeParam = $"{time.Minutes:D2}:{time.Seconds:D2}.{time.Milliseconds:D2}";
|
||||||
|
_logger.LogDebug("Extracting frame: {videoPath} at {time} to {outputPath}", videoPath, timeParam, outputPath);
|
||||||
|
var ffmpegProcess = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = FFMPEG_PATH,
|
||||||
|
Arguments = $"-y -i {videoPath} -ss {timeParam} -vframes 1 {outputPath}",
|
||||||
|
RedirectStandardOutput = false,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardError = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ffmpegProcess.Start();
|
||||||
|
_logger.LogDebug("Waiting for frame extraction... process ID: {Id}", ffmpegProcess.Id);
|
||||||
|
await ffmpegProcess.WaitForExitAsync();
|
||||||
|
_logger.LogInformation("Frame extracted successfully!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "An error occurred while extracting the frame");
|
||||||
|
throw new Exception("There was an error extracting the frame", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user