Skip to content

Commit ef8e82b

Browse files
committed
fix(*)
1 parent ce87a33 commit ef8e82b

3 files changed

Lines changed: 33 additions & 14 deletions

File tree

android/gradle.properties

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Dconsole.encoding=UTF-8
22
android.useAndroidX=true
33
android.enableJetifier=true
4-
# systemProp.http.proxyHost=127.0.0.1
5-
# systemProp.http.proxyPort=7890
6-
# systemProp.https.proxyHost=127.0.0.1
7-
# systemProp.https.proxyPort=7890
4+
systemProp.http.proxyHost=127.0.0.1
5+
systemProp.http.proxyPort=7890
6+
systemProp.https.proxyHost=127.0.0.1
7+
systemProp.https.proxyPort=7890
88
# systemProp.socks.proxyHost=127.0.0.1
99
# systemProp.socks.proxyPort=7898

lib/recorder/ffmpeg/ffmpeg_command_builder.dart

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,43 @@ class FFmpegCommandBuilder {
2020
final ua = headers?['user-agent'] ?? defaultUserAgent;
2121
final headerStr = _buildHeader(headers);
2222
final normalizedOutputPath = '$outputDir${Platform.pathSeparator}%Y%m%d_%H%M%S.ts';
23-
final rwTimeoutMicro = (rwTimeout * 1000000).clamp(0, 2147483647);
24-
2523
final args = <String>[
2624
'-y',
2725
'-hide_banner',
2826
'-loglevel', 'info',
27+
// 允许的协议白名单,确保直播流能正常加载
2928
'-protocol_whitelist', 'httpproxy,udp,rtp,tcp,tls,data,file,http,https,crypto',
29+
30+
// --- 重连与网络优化 ---
3031
'-reconnect', '1',
3132
'-reconnect_streamed', '1',
3233
'-reconnect_delay_max', '2',
3334
'-reconnect_at_eof', '1',
34-
'-rw_timeout', rwTimeoutMicro.toString(),
35+
'-rw_timeout', '${rwTimeout * 1000000}', // 转化为微秒
3536
'-max_delay', '5000000',
3637
'-thread_queue_size', threadQueueSize.toString(),
37-
'-user_agent', ua,
38-
if (headerStr.isNotEmpty) ...['-headers', _quote(headerStr)], //关键:headers
39-
'-i', url,
38+
39+
// --- 身份伪装 ---
40+
'-user_agent', _quote(ua),
41+
if (headerStr.isNotEmpty) ...['-headers', _quote(headerStr)], // 关键:headers必须包裹在引号内
42+
// --- 输入 ---
43+
'-i', _quote(url),
44+
45+
// --- 轨道处理 ---
46+
// 使用 copy 模式避免 CPU 占用过高
4047
'-map', preferBestStream ? '0:v:0' : '0:v',
4148
'-map', preferBestStream ? '0:a:0' : '0:a',
4249
'-c', 'copy',
50+
51+
// --- 分段逻辑 ---
4352
'-f', 'segment',
4453
'-segment_format', 'mpegts',
4554
'-segment_time', segmentTime.toString(),
4655
'-reset_timestamps', '1',
4756
'-strftime', '1',
48-
normalizedOutputPath,
57+
58+
// 输出路径 (使用 .ts 格式以防断流导致文件损坏)
59+
_quote(normalizedOutputPath),
4960
];
5061

5162
return args.join(' ');
@@ -57,6 +68,8 @@ class FFmpegCommandBuilder {
5768
.where((e) => e.key.toLowerCase() != 'user-agent')
5869
.map((e) => '${e.key}: ${e.value}')
5970
.join('\r\n');
71+
72+
// FFmpeg 要求 headers 末尾也必须有换行符
6073
return lines.isEmpty ? '' : '$lines\r\n';
6174
}
6275
}

lib/recorder/services/ffmpeg_service.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,18 @@ class FFmpegService {
6262
});
6363
ffempgSession.setCompleteCallback((completedSession) {
6464
final code = completedSession.getReturnCode();
65-
final success = ReturnCode.isSuccess(code);
66-
log('FFmpeg complete => taskId: $taskId;successCode: $code ');
65+
bool isNormalExit = [
66+
0, // 正常完成
67+
255, // 手动停止
68+
-1094995529, // 断流/无数据
69+
-1077350400, // 超时/网络断开
70+
-1005272104, // 读取中断
71+
].contains(code);
72+
log('FFmpeg complete => taskId: $taskId; code: $code ');
6773
onEvent(
6874
FFmpegEvent(
6975
taskId: taskId,
70-
type: success ? FFmpegEventType.complete : FFmpegEventType.error,
76+
type: isNormalExit ? FFmpegEventType.complete : FFmpegEventType.error,
7177
data: {"code": code},
7278
),
7379
);

0 commit comments

Comments
 (0)