fix: restore native FLV reconnect with curl fallback
This commit is contained in:
@@ -114,12 +114,100 @@ public sealed class FfmpegFailureClassificationTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("https://example.test/live.flv", "flv", true)]
|
||||
[InlineData("https://example.test/live.m3u8", "hls", false)]
|
||||
[InlineData("https://example.test/playlist", "hls", false)]
|
||||
public void HttpInput_UsesCurlExceptForHls(string url, string protocol, bool expected)
|
||||
[InlineData("https://example.test/live.flv", "flv", false, false)]
|
||||
[InlineData("https://example.test/live.flv", "flv", true, true)]
|
||||
[InlineData("https://example.test/live.m3u8", "hls", true, false)]
|
||||
[InlineData("https://example.test/playlist", "hls", true, false)]
|
||||
public void CurlPipe_IsOnlyUsedForExplicitFlvFallback(
|
||||
string url,
|
||||
string protocol,
|
||||
bool useCurlFallback,
|
||||
bool expected)
|
||||
{
|
||||
Assert.Equal(expected, FfmpegService.ShouldUseCurlPipe(url, protocol));
|
||||
Assert.Equal(expected, FfmpegService.ShouldUseCurlPipe(url, protocol, useCurlFallback));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NativeFlvInput_UsesFfmpegReconnectByDefault()
|
||||
{
|
||||
var arguments = FfmpegService.BuildArgumentList(
|
||||
"https://cdn.example.test/live.flv",
|
||||
"/tmp/output.ts",
|
||||
RecordOutputFormat.Ts,
|
||||
RecordSaveMode.SingleFile,
|
||||
1,
|
||||
RecordingTemplateType.StreamCopy,
|
||||
true,
|
||||
10,
|
||||
30_000_000,
|
||||
30,
|
||||
null,
|
||||
"flv",
|
||||
"h264",
|
||||
FfmpegService.FfmpegInputOptionProfile.Baseline);
|
||||
|
||||
Assert.Contains("https://cdn.example.test/live.flv", arguments);
|
||||
Assert.DoesNotContain("pipe:0", arguments);
|
||||
Assert.Contains("-reconnect", arguments);
|
||||
Assert.Contains("-reconnect_streamed", arguments);
|
||||
Assert.Contains("-reconnect_at_eof", arguments);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("flv", true, false, true)]
|
||||
[InlineData("flv", true, true, false)]
|
||||
[InlineData("flv", false, false, false)]
|
||||
[InlineData("hls", true, false, false)]
|
||||
public void OverlongHeaders_UsesCurlFallbackAtMostOnce(
|
||||
string protocol,
|
||||
bool hasOverlongHeadersFailure,
|
||||
bool hasTriedCurlFallback,
|
||||
bool expected)
|
||||
{
|
||||
Assert.Equal(
|
||||
expected,
|
||||
FfmpegService.ShouldFallbackToCurl(protocol, hasOverlongHeadersFailure, hasTriedCurlFallback));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CurlFallback_UsesPipeWithFiniteRetriesAndPreservesHeaders()
|
||||
{
|
||||
var headers = new StreamInputHeaders(
|
||||
"RecorderTest/1.0",
|
||||
"https://live.example.test/room",
|
||||
"session=abc",
|
||||
new Dictionary<string, string> { ["X-Test"] = "yes" });
|
||||
var ffmpegArguments = FfmpegService.BuildArgumentList(
|
||||
"https://cdn.example.test/live.flv",
|
||||
"/tmp/output.ts",
|
||||
RecordOutputFormat.Ts,
|
||||
RecordSaveMode.SingleFile,
|
||||
1,
|
||||
RecordingTemplateType.StreamCopy,
|
||||
true,
|
||||
10,
|
||||
30_000_000,
|
||||
30,
|
||||
headers,
|
||||
"flv",
|
||||
"h264",
|
||||
FfmpegService.FfmpegInputOptionProfile.Baseline,
|
||||
useCurlFallback: true);
|
||||
var curlArguments = FfmpegService.BuildCurlArgumentList(
|
||||
"https://cdn.example.test/live.flv",
|
||||
headers);
|
||||
|
||||
Assert.Contains("pipe:0", ffmpegArguments);
|
||||
Assert.DoesNotContain("-reconnect", ffmpegArguments);
|
||||
Assert.Contains("--show-error", curlArguments);
|
||||
Assert.Contains("--fail", curlArguments);
|
||||
Assert.Contains("--retry", curlArguments);
|
||||
Assert.Contains("--retry-all-errors", curlArguments);
|
||||
Assert.Contains("--retry-max-time", curlArguments);
|
||||
Assert.Contains("RecorderTest/1.0", curlArguments);
|
||||
Assert.Contains("https://live.example.test/room", curlArguments);
|
||||
Assert.Contains("session=abc", curlArguments);
|
||||
Assert.Contains("X-Test: yes", curlArguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -145,7 +233,8 @@ public sealed class FfmpegFailureClassificationTests
|
||||
headers,
|
||||
"hls",
|
||||
"h264",
|
||||
FfmpegService.FfmpegInputOptionProfile.Baseline);
|
||||
FfmpegService.FfmpegInputOptionProfile.Baseline,
|
||||
useCurlFallback: true);
|
||||
|
||||
Assert.Contains("https://cdn.example.test/live/index.m3u8", arguments);
|
||||
Assert.DoesNotContain("pipe:0", arguments);
|
||||
@@ -182,6 +271,27 @@ public sealed class FfmpegFailureClassificationTests
|
||||
Assert.Contains("-reset_timestamps", arguments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecoveryContext_LeavesCurlAfterExitWithoutResettingOneShotBudget()
|
||||
{
|
||||
var curlContext = FfmpegService.InitialRecoveryContext with
|
||||
{
|
||||
UseCurlFallback = true,
|
||||
HasTriedCurlFallback = true
|
||||
};
|
||||
|
||||
var nextContext = FfmpegService.AdvanceRecoveryContext(
|
||||
curlContext,
|
||||
curlContext.InputOptionProfile,
|
||||
"flv",
|
||||
"flv",
|
||||
refreshedStream: true);
|
||||
|
||||
Assert.False(nextContext.UseCurlFallback);
|
||||
Assert.True(nextContext.HasTriedCurlFallback);
|
||||
Assert.True(nextContext.HasRetriedWithRefreshedStream);
|
||||
Assert.False(FfmpegService.ShouldFallbackToCurl("flv", true, nextContext.HasTriedCurlFallback));
|
||||
}
|
||||
[Fact]
|
||||
public void RecoveryContext_PreservesBudgetAcrossHlsFallbackAndReachesTimestampTranscode()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user