mirror of
https://github.com/unclshura/splitter.git
synced 2026-09-20 07:13:38 +00:00
Loseless split is back. Very fast now. Using key frames.
This commit is contained in:
parent
77bae6e392
commit
092bc88d58
@ -79,8 +79,8 @@ public class JobProcessor(ILogger logger) : LoggingBase(logger, 0), IJobProcesso
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//processorFactory = i => new PassthroughSplitter(i, _logger);
|
processorFactory = i => new PassthroughSplitter(i, _logger);
|
||||||
processorFactory = i => new ReencodeSplitter(i, _logger);
|
//processorFactory = i => new ReencodeSplitter(i, _logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
var segmentsToUse = predefinedSegments;
|
var segmentsToUse = predefinedSegments;
|
||||||
|
|||||||
@ -82,8 +82,15 @@ public sealed class PassthroughSplitter : LoggingBase, ISegmentProcessor
|
|||||||
var start = job.SegmentStart;
|
var start = job.SegmentStart;
|
||||||
var length = job.SegmentLength;
|
var length = job.SegmentLength;
|
||||||
|
|
||||||
|
// Probe next keyframe packet within a 5-second window
|
||||||
|
var nextKey = ProbeNextKeyframePacket(inputFile, start);
|
||||||
|
|
||||||
|
// Adjust by subtracting X.XX seconds
|
||||||
|
const double shiftBack = 0.1;
|
||||||
|
var seekPos = nextKey > shiftBack ? nextKey - shiftBack : 0.0;
|
||||||
|
|
||||||
var args =
|
var args =
|
||||||
$"-ss {start.ToString(CultureInfo.InvariantCulture)} " +
|
$"-ss {seekPos.ToString(CultureInfo.InvariantCulture)} " +
|
||||||
$"-i \"{inputFile}\" " +
|
$"-i \"{inputFile}\" " +
|
||||||
$"-t {length.ToString(CultureInfo.InvariantCulture)} " +
|
$"-t {length.ToString(CultureInfo.InvariantCulture)} " +
|
||||||
$"-c copy {string.Join(" ", job.Job.Passthrough)} " +
|
$"-c copy {string.Join(" ", job.Job.Passthrough)} " +
|
||||||
@ -100,4 +107,60 @@ public sealed class PassthroughSplitter : LoggingBase, ISegmentProcessor
|
|||||||
|
|
||||||
return Process.Start(psi) ?? throw new Exception("Failed to start ffmpeg passthrough.");
|
return Process.Start(psi) ?? throw new Exception("Failed to start ffmpeg passthrough.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double ProbeNextKeyframePacket(string inputFile, double segmentStart, double window = 11.0)
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "ffprobe",
|
||||||
|
Arguments =
|
||||||
|
"-select_streams v " +
|
||||||
|
$"-read_intervals \"{(segmentStart-0.1).ToString(CultureInfo.InvariantCulture)}%+{window.ToString(CultureInfo.InvariantCulture)}\" " +
|
||||||
|
"-skip_frame nokey " +
|
||||||
|
"-show_packets " +
|
||||||
|
"-show_entries packet=pts_time,flags " +
|
||||||
|
"-of compact=p=0 " +
|
||||||
|
"-v quiet " +
|
||||||
|
$"\"{inputFile}\"",
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using var p = Process.Start(psi);
|
||||||
|
var output = p!.StandardOutput.ReadToEnd();
|
||||||
|
p.WaitForExit();
|
||||||
|
|
||||||
|
double best = double.MaxValue;
|
||||||
|
|
||||||
|
foreach (var line in output.Split('\n'))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Example line:
|
||||||
|
// pts_time=23.520000|flags=K__
|
||||||
|
var parts = line.Split('|');
|
||||||
|
if (parts.Length < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var ptsPart = parts[0].Trim(); // pts_time=23.520000
|
||||||
|
var flagsPart = parts[1].Trim(); // flags=K__
|
||||||
|
|
||||||
|
if (!flagsPart.Contains("K"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var ptsStr = ptsPart.Replace("pts_time=", "");
|
||||||
|
if (!double.TryParse(ptsStr, NumberStyles.Float, CultureInfo.InvariantCulture, out var pts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( best == double.MaxValue)
|
||||||
|
best = pts;
|
||||||
|
if (pts > segmentStart)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return best == double.MaxValue ? segmentStart : best;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user