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
RyuJongJin 2026-10-02 20:16:58 +09:00
parent bf6429dc76
commit 467c0ea8b5
4 changed files with 34 additions and 4 deletions

View File

@ -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();

View File

@ -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`)

View File

@ -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) {

View File

@ -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