ffmpeg提取通义万象视频封面超时

ffmpeg提取通义万象视频第一帧的时候,一直出现超时的问题,然后我去网上遍寻答案,首先是有说AI生成的视频的编码格式与我们一般标准格式的视频不一致,会把原数据从头部移至尾部,为此写了一个这样的方法,以此来把尾部的元数据提取至头部。

private File standardizeVideo(File originalVideo) { try { File tempVideo = File.createTempFile("standard_", ".mp4"); // 只修复封装,不转码!速度极快! ProcessBuilder pb = new ProcessBuilder( "ffmpeg", "-y", "-i", originalVideo.getAbsolutePath(), "-c:v", "copy", "-c:a", "copy", "-movflags", "faststart", // 把 moov 移到开头 tempVideo.getAbsolutePath() ); Process process = pb.start(); process.waitFor(5, TimeUnit.SECONDS); return tempVideo; } catch (Exception e) { log.error("视频标准化失败", e); return null; } }

但是依旧没有解决超时的问题,而后又使用ffmpeg的强制提取第一帧命令行

ProcessBuilder pb = new ProcessBuilder( "ffmpeg", "-y", "-probesize", "50M", // 扩大探测大小(修复万象视频) "-analyzeduration", "100M",// 延长分析时间(修复万象视频) "-i", videoFile.getAbsolutePath(), "-ss", "00:00:00.500", "-vf", "scale=iw:ih", // 强制渲染一帧 "-vframes", "1", "-q:v", "2", coverFile.getAbsolutePath() );

但是依旧没有解决。
最后发现其实是缓存区满了,导致子进程挂起,所以应该启动单独线程消费 ffmpeg 的输出流

new Thread(() -> { try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { // 丢弃输出,防止缓冲区满 } } catch (Exception e) { // 忽略 } }).start();

使用这个代码来做到丢弃输出,防止缓冲区爆满的效果。
最后ffmpeg可以正常提取视频第一帧。