-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFFmpegProgress.cs
More file actions
82 lines (74 loc) · 3.35 KB
/
Copy pathFFmpegProgress.cs
File metadata and controls
82 lines (74 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
namespace Ffmpegkit.Net;
/// <summary>
/// A progress sample taken while an FFmpeg command runs.
/// </summary>
/// <remarks>
/// Both platforms report the same statistics shape (FFmpegKit's own <c>Statistics</c> type, Java
/// on Android and Objective-C on iOS) at the same cadence, so this is a single record rather than
/// one per platform - only the conversion in <c>Platforms/Android</c> / <c>Platforms/iOS</c> differs.
/// </remarks>
/// <param name="Position">How far into the output FFmpeg has written.</param>
/// <param name="Percent">
/// Fraction of the way through, 0 to 1, or null when the total duration is not known.
/// </param>
/// <param name="SizeBytes">Bytes written so far.</param>
/// <param name="Bitrate">Current bit rate in kbit/s, or null when FFmpeg reports none.</param>
/// <param name="Speed">Encoding speed relative to realtime; 2.0 means twice as fast as playback.</param>
/// <param name="VideoFrameNumber">Frames encoded so far, 0 for audio-only work.</param>
/// <param name="VideoFps">Current frames per second, 0 for audio-only work.</param>
public sealed record FFmpegProgress(
TimeSpan Position,
double? Percent,
long SizeBytes,
double? Bitrate,
double Speed,
int VideoFrameNumber,
float VideoFps)
{
/// <summary>Estimated time remaining, or null without a total duration or a usable speed.</summary>
/// <remarks>
/// Derived from <see cref="Speed"/>, which FFmpeg reports relative to realtime, so this is
/// only as steady as the encode is. Treat it as an indication, not a countdown.
/// </remarks>
public TimeSpan? EstimatedTimeRemaining { get; init; }
/// <summary>
/// Builds a sample from the raw numbers each platform's <c>Statistics</c> type reports.
/// </summary>
/// <remarks>
/// Shared so the clamping and null-handling rules - a negative pre-first-frame
/// <paramref name="timeMs"/>, a zero bitrate before FFmpeg has enough output to measure one -
/// are applied identically on every platform, even though each hands the raw numbers over
/// through a differently-typed <c>Statistics</c> object.
/// </remarks>
internal static FFmpegProgress From(
double timeMs,
long sizeBytes,
double bitrate,
double speed,
int videoFrameNumber,
float videoFps,
TimeSpan? totalDuration)
{
// FFmpeg can report a negative time before the first frame is written.
var position = TimeSpan.FromMilliseconds(Math.Max(timeMs, 0));
double? percent = null;
TimeSpan? remaining = null;
if (totalDuration is { } total && total > TimeSpan.Zero)
{
percent = Math.Clamp(position.TotalMilliseconds / total.TotalMilliseconds, 0, 1);
if (speed > 0)
{
var outstanding = total - position;
if (outstanding > TimeSpan.Zero)
remaining = TimeSpan.FromSeconds(outstanding.TotalSeconds / speed);
}
}
// FFmpeg reports a bitrate of 0 (and occasionally a negative one) before it has enough
// output to measure one.
var reportedBitrate = bitrate > 0 ? bitrate : (double?)null;
return new FFmpegProgress(position, percent, sizeBytes, reportedBitrate, speed, videoFrameNumber, videoFps)
{
EstimatedTimeRemaining = remaining,
};
}
}