v2026.10.02_001: Android MKV 만들기가 끝나도 몇 분씩 "작업 중" 으로 멈추던 문제 수정
- ffmpeg-kit 플러그인 사본: 통계(진행률) 이벤트를 세션마다 0.25초에 한 번만 Dart 로 보냄 (프레임마다 보내 메인 스레드 줄이 밀리고 완료 이벤트가 늦게 도착, 그동안 다른 작업 버튼이 모두 잠김) - FfmpegKitMediaTool: 진행률이 0.5% 이상 바뀔 때만 화면 갱신 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>main
parent
bf6429dc76
commit
467c0ea8b5
|
|
@ -71,6 +71,7 @@ class FfmpegKitMediaTool implements MediaTool {
|
|||
final totalMs = duration?.inMilliseconds ?? 0;
|
||||
final done = Completer<void>();
|
||||
final errTail = <String>[];
|
||||
var lastProgress = 0.0;
|
||||
final session = await FFmpegKit.executeWithArgumentsAsync(
|
||||
a,
|
||||
(s) async {
|
||||
|
|
@ -93,9 +94,12 @@ class FfmpegKitMediaTool implements MediaTool {
|
|||
}
|
||||
},
|
||||
(st) {
|
||||
if (onProgress != null && totalMs > 0 && st.getTime() > 0) {
|
||||
onProgress((st.getTime() / totalMs).clamp(0.0, 1.0));
|
||||
}
|
||||
if (onProgress == null || totalMs <= 0 || st.getTime() <= 0) return;
|
||||
// 화면을 다시 그리는 일이 많지 않도록 0.5% 이상 바뀔 때만 알린다
|
||||
final x = (st.getTime() / totalMs).clamp(0.0, 1.0);
|
||||
if (x - lastProgress < 0.005) return;
|
||||
lastProgress = x;
|
||||
onProgress(x);
|
||||
},
|
||||
);
|
||||
final id = session.getSessionId();
|
||||
|
|
|
|||
|
|
@ -9,3 +9,8 @@ JJ_MKVMaker 의 Windows 판은 동봉한 ffmpeg.exe 를 쓰므로 필요 없다.
|
|||
## 수정
|
||||
- pubspec.yaml: 플러그인 플랫폼을 android 만 남김 (ios · macos · windows · linux 제거)
|
||||
- windows · linux · macos · ios · example 폴더 제거
|
||||
|
||||
## 통계 이벤트 줄이기 (2026-10-02)
|
||||
FFmpeg 는 프레임마다 통계(진행률)를 보낸다. 17분 영상 하나에 수만 개가 Dart 로 넘어가 메인 스레드 줄이 밀리고,
|
||||
완료 이벤트가 그 뒤에 서 있어 FFmpeg 가 4초 만에 끝나도 앱은 2분 넘게 "작업 중" 으로 남았다.
|
||||
- android/.../FFmpegKitFlutterPlugin.java: 통계는 세션마다 0.25초에 한 번만 보낸다 (`shouldEmitStatistics`)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
});
|
||||
|
||||
FFmpegKitConfig.enableStatisticsCallback(statistics -> {
|
||||
// JJ_PATCH: FFmpeg 는 프레임마다 통계를 보낸다 (긴 영상이면 수만 개).
|
||||
// 모두 Dart 로 보내면 메인 스레드 줄이 밀려 완료 이벤트가 몇 분씩 늦게 도착한다 → 세션마다 0.25초에 한 번만
|
||||
if (!shouldEmitStatistics(statistics)) {
|
||||
return;
|
||||
}
|
||||
for (FFmpegKitFlutterPlugin plugin : attachedPlugins) {
|
||||
if (plugin.statisticsEnabled.get() && plugin.eventSink != null) {
|
||||
plugin.emitStatistics(statistics);
|
||||
|
|
@ -169,7 +174,23 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
});
|
||||
}
|
||||
|
||||
// JJ_PATCH: 세션별 마지막 통계 전송 시각 (완료되면 지운다)
|
||||
private static final long STATISTICS_INTERVAL_MS = 250;
|
||||
private static final java.util.concurrent.ConcurrentHashMap<Long, Long> lastStatisticsAt =
|
||||
new java.util.concurrent.ConcurrentHashMap<>();
|
||||
|
||||
private static boolean shouldEmitStatistics(final Statistics statistics) {
|
||||
final long now = android.os.SystemClock.uptimeMillis();
|
||||
final Long last = lastStatisticsAt.get(statistics.getSessionId());
|
||||
if (last != null && now - last < STATISTICS_INTERVAL_MS) {
|
||||
return false;
|
||||
}
|
||||
lastStatisticsAt.put(statistics.getSessionId(), now);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void broadcastSession(final Session session) {
|
||||
lastStatisticsAt.remove(session.getSessionId());
|
||||
boolean delivered = false;
|
||||
for (FFmpegKitFlutterPlugin plugin : attachedPlugins) {
|
||||
if (plugin.eventSink != null) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 2026.10.1+3
|
||||
version: 2026.10.2+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.13.4
|
||||
|
|
|
|||
Loading…
Reference in New Issue