FFmpeg是领先的多媒体框架,能够解码、编码、 转码、复用、解复用、流、过滤和播放 几乎所有人类和机器创建的东西。它支持最模糊的古老格式,直到最前沿。无论它们是由某个标准委员会、社区还是公司设计的。它还具有高度的可移植性:FFmpeg 在各种构建环境、机器架构和配置下跨 Linux、Mac OS X、Microsoft Windows、BSD、Solaris 等 编译、运行和通过我们的测试基础架构 FATE 。

官网:
https://ffmpeg.p2hp.com/index.html (中文)
FFmpeg除了做转码外,也支持通过TCP或者UDP协议,拉取RSTP视频流,实时将视频流转为MP4文件存到本地,支持直接拉取H264和H265。
例如,当前我们使用海康相机来进行测试,拉取的为H265视频流,拉取到视频流后,本地再转为H264格式,然后把音频同时转化,然后按照时间存为Mp4。
因为H265占用宽带更小,因此我们优先采用该格式,在不考虑宽带时,也可以考虑直接拉取H264。
海康相机是支持直接拉取视频流的,例如我们使用VLC软件(https://www.videolan.org/vlc/index.html),就可以直接预览视频

此时我们使用的是RSTP流, URL格式为:rtsp://用户名:密码@IP:RSTP端口/h265(或h264)

然后我们就能预览到视频了

下面我们通过FFmpeg的rtsp_transport命令,拉取RSTP视频流,并转码存到本地。
下载FFmpeg并配置到环境变量,如何配置可以自行查询相关资料。
先看完整代码,这里写了一个Main方法,如何集成到项目,自行考量
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 利用ffmpeg实时拉取视频流并保存到本地MP4
*/
@Slf4j
public class FfmpegWatcher {
private static final String FFMPEG_PATH = "ffmpeg";
private static final String OUTPUT_DIR = "D:\\temp";
private static final long RESTART_DELAY_MS = 5_000;
private static final String CAMERA_IP = "192.168.110.114";
private static final String CAMERA_PASSWORD = "111111";
private static final String CAMERA_USER = "admin";
private static final String CAMERA_RTSP_PORT = "554";
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private volatile Process ffmpegProcess = null;
// 关键:使用 volatile 确保线程可见性
private volatile Long lastLog = null;
// 新增:是否已因超时触发过 destroy(防止重复 kill)
private volatile boolean destroyedDueToTimeout = false;
private Thread watchdog = null;
public static void main(String[] args) {
FfmpegWatcher watcher = new FfmpegWatcher();
watcher.addShutdownHook();
watcher.monitor();
watcher.startWatchdog();
try {
new CountDownLatch(1).await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 启动看门狗线程:每 N 秒检查一次 lastLog 是否超时
*/
private void startWatchdog() {
watchdog = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(1000); // 每N秒检查一次
if (ffmpegProcess != null && ffmpegProcess.isAlive() && !destroyedDueToTimeout) {
if (lastLog != null) {
long now = System.currentTimeMillis();
if (now - lastLog > 10_000) { // 超过10秒无日志
log.info("检测到 ffmpeg 超过 10 秒无输出,疑似卡死,正在强制重启...");
// 尝试发送 'q' 信号优雅退出
// 这样已经录制的视频文件,会停止录制,保留当前录制不完成的MP4文件
try {
ffmpegProcess.getOutputStream().write('q');
ffmpegProcess.getOutputStream().flush();
} catch (IOException e) {
log.error("发送 'q' 信号给 ffmpeg 失败", e);
}
destroyedDueToTimeout = true; // 防止重复 kill
ffmpegProcess.destroy(); // 触发 waitFor 返回
lastLog = System.currentTimeMillis(); // 重新计时
}
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
break; // 退出循环
} catch (Exception e) {
log.error("看门狗线程异常", e);
}
}
}, "ffmpeg-watchdog");
watchdog.setDaemon(true);
watchdog.start();
}
/**
* 构建 ffmpeg 命令
*/
private List<String> buildCommand() {
List<String> cmd = new ArrayList<>();
cmd.add(FFMPEG_PATH);
cmd.add("-rtsp_transport");
cmd.add("tcp");
String password = URLEncoder.encode(CAMERA_PASSWORD, StandardCharsets.UTF_8);
cmd.add("-i");
cmd.add(StrUtil.format("rtsp://{}:{}@{}:{}/h265", CAMERA_USER, password, CAMERA_IP, CAMERA_RTSP_PORT));
cmd.add("-c:v");
cmd.add("libx264");
cmd.add("-preset");
cmd.add("veryfast"); // 更“慢”的 preset 通常能获得更好的压缩率(即相同质量下文件更小)。可选值从快到慢:ultrafast → superfast → veryfast → faster → fast → medium → slow → slower → veryslow
cmd.add("-crf");
cmd.add("23"); // 取值范围一般为 0–51:0 = 无损(文件极大)18–23 = 视觉无损到高质量(推荐范围)28 = 较低质量,较小体积(适合网络传输或对画质要求不高)51 = 最差质量
cmd.add("-c:a");
cmd.add("aac");
cmd.add("-b:a");
cmd.add("128k");
cmd.add("-f");
cmd.add("segment");
cmd.add("-segment_time");
cmd.add("60"); // 分割时长
cmd.add("-strftime");
cmd.add("1");
cmd.add(OUTPUT_DIR + File.separator + CAMERA_IP + "_%Y%m%d_%H%M%S.mp4");
return cmd;
}
/**
* 启动 ffmpeg 进程
*/
private void startProcess() throws IOException {
new File(OUTPUT_DIR).mkdirs();
List<String> command = buildCommand();
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
ffmpegProcess = pb.start();
lastLog = System.currentTimeMillis(); // 重新计时
Thread logForwarder = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(ffmpegProcess.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
log.debug("[FFMPEG] {}", line);
lastLog = System.currentTimeMillis(); // 更新最后日志时间
if(line.contains("Opening") && line.contains("for writing")) {
String fileName = extractFileName(line);
log.info("开始录制文件:{}", fileName);
}
}
log.debug("[FFMPEG] 日志读取线程结束,ffmpeg 进程已终止");
} catch (IOException e) {
log.error("读取 ffmpeg 输出流时异常", e);
}
}, "ffmpeg-log-forwarder");
logForwarder.setDaemon(true);
logForwarder.start();
log.info("ffmpeg 录像开始, 进程号 = {}", ffmpegProcess.pid());
}
/**
* 注册和控制 ffmpeg 进程
*/
private void monitor() {
executor.submit(() -> {
while (!executor.isShutdown()) {
try {
if (ffmpegProcess == null) {
destroyedDueToTimeout = false; // 重置标志
startProcess();
}
int exitCode = ffmpegProcess.waitFor();
log.error("ffmpeg 结束录像,退出信号 = {}", exitCode);
Thread.sleep(RESTART_DELAY_MS);
ffmpegProcess = null;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (IOException e) {
log.error("ffmpeg 启动录像失败", e);
try {
Thread.sleep(RESTART_DELAY_MS);
} catch (InterruptedException ignored) {
}
}
}
});
}
/**
* 添加关闭钩子
*/
private void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("JVM 关闭中,正在清理 ffmpeg 进程...");
// 中断并等待 watchdog 结束
if (watchdog != null && watchdog.isAlive()) {
watchdog.interrupt();
}
if (ffmpegProcess != null && ffmpegProcess.isAlive()) {
// 尝试发送 'q' 信号优雅退出
// 这样已经录制的视频文件,会停止录制,保留当前录制不完成的MP4文件
try {
ffmpegProcess.getOutputStream().write('q');
ffmpegProcess.getOutputStream().flush();
} catch (IOException e) {
log.error("发送 'q' 信号给 ffmpeg 失败", e);
}
try {
if (!ffmpegProcess.waitFor(5, TimeUnit.SECONDS)) {
ffmpegProcess.destroyForcibly();
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
executor.shutdownNow();
}));
}
/**
* 先取出完整路径,再用 Paths 获取文件名
* */
public String extractFileName(String logLine) {
// 只取单引号之间的内容(完整路径)
String pathRegex = "Opening\\s*'([^']+)'";
Matcher m = Pattern.compile(pathRegex).matcher(logLine);
if (m.find()) {
String fullPath = m.group(1); // D:\temp\192.168.110.114_20251110_143020.mp4
// Paths 会自动识别 Windows 反斜杠
return Paths.get(fullPath).getFileName().toString(); // 192.168.110.114_20251110_143020.mp4
}
return null;
}
}方法buildCommand是组装相关命令,相关命令解释已经备注。
这里特别要注意的是,要注意addShutdownHook方法,注册一个钩子,在程序退出时,终止录制。如果是强制停止,比如Linux上的Kill -9,那么程序不能完成处理当前的文件,导致最后一个文件不能播放。
还要注意的是,如果产生网络卡顿,就会堵塞,所以我这里采用看门狗(startWatchdog方法)来监控录制情况,如果长时间没有录制,则终止重启。
怎么知道在录制呢?就是方法startProcess里面的logForwarder线程,会实时接收ffmpeg的打印,实际上ffmpeg会一直打印每一帧的处理情况,如果有打印就说明在录制。
同时在该线程里面,通过正则来找到当前正在录制的是哪个文件。
执行能看到执行日志
19:23:54.054 c.g.o.c.FfmpegWatcher : 168 ffmpeg 录像开始, 进程号 = 15092 19:23:54.155 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] ffmpeg version 6.0-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers 19:23:54.156 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] built with gcc 12.2.0 (Rev10, Built by MSYS2 project) 19:23:54.156 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint 19:23:54.156 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libavutil 58. 2.100 / 58. 2.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libavcodec 60. 3.100 / 60. 3.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libavformat 60. 3.100 / 60. 3.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libavdevice 60. 1.100 / 60. 1.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libavfilter 9. 3.100 / 9. 3.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libswscale 7. 1.100 / 7. 1.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libswresample 4. 10.100 / 4. 10.100 19:23:54.157 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] libpostproc 57. 1.100 / 57. 1.100 19:23:54.422 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [hevc @ 000002f0a9aa5840] PPS id out of range: 0 19:23:54.422 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Last message repeated 1 times 19:23:54.422 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [hevc @ 000002f0a9aa5840] Error parsing NAL unit #0. 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Input #0, rtsp, from 'rtsp://admin:Gtgj%402020@192.168.110.114:554/h265': 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Metadata: 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] title : Media Presentation 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Duration: N/A, start: 0.000000, bitrate: N/A 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:0: Video: hevc (Main), yuvj420p(pc, bt709), 2688x1520, 50 fps, 25.08 tbr, 90k tbn 19:23:55.215 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:1: Audio: pcm_alaw, 8000 Hz, mono, s16, 64 kb/s 19:23:55.220 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream mapping: 19:23:55.220 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:0 -> #0:0 (hevc (native) -> h264 (libx264)) 19:23:55.220 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:1 -> #0:1 (pcm_alaw (native) -> aac (native)) 19:23:55.220 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Press [q] to stop, [?] for help 19:23:55.221 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [aac @ 000002f0a9c113c0] Too many bits 16384.000000 > 6144 per frame requested, clamping to max 19:23:55.224 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [hevc @ 000002f0a9c117c0] Could not find ref with POC 0 19:23:55.283 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 19:23:55.288 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] profile High, level 5.0, 4:2:0, 8-bit 19:23:55.288 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] 264 - core 164 r3106 eaa68fa - H.264/MPEG-4 AVC codec - Copyleft 2003-2023 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=30 lookahead_threads=10 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 19:23:55.289 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [segment @ 000002f0a9d5e800] Opening 'D:\temp\192.168.110.114_20251112_192355.mp4' for writing 19:23:55.292 c.g.o.c.FfmpegWatcher : 157 开始录制文件:192.168.110.114_20251112_192355.mp4 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Output #0, segment, to 'D:\temp\192.168.110.114_%Y%m%d_%H%M%S.mp4': 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Metadata: 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] title : Media Presentation 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] encoder : Lavf60.3.100 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:0: Video: h264, yuvj420p(pc, bt709, progressive), 2688x1520, q=2-31, 25.08 fps, 19264 tbn 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Metadata: 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] encoder : Lavc60.3.100 libx264 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Side data: 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Stream #0:1: Audio: aac (LC), 8000 Hz, mono, fltp, 48 kb/s 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] Metadata: 19:23:55.293 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] encoder : Lavc60.3.100 aac 19:23:55.300 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 0 fps=0.0 q=0.0 size=N/A time=00:00:00.25 bitrate=N/A dup=2 drop=0 speed= 4.4x 19:23:55.833 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 0 fps=0.0 q=0.0 size=N/A time=00:00:01.02 bitrate=N/A dup=2 drop=0 speed=1.74x 19:23:56.317 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 0 fps=0.0 q=0.0 size=N/A time=00:00:01.53 bitrate=N/A dup=2 drop=0 speed= 1.4x 19:23:56.857 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 5 fps=3.1 q=28.0 size=N/A time=00:00:02.04 bitrate=N/A dup=2 drop=0 speed=1.28x 19:23:57.351 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 18 fps=8.5 q=28.0 size=N/A time=00:00:02.56 bitrate=N/A dup=2 drop=0 speed=1.21x 19:23:57.873 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 31 fps= 12 q=28.0 size=N/A time=00:00:03.07 bitrate=N/A dup=2 drop=0 speed=1.17x 19:23:58.405 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 43 fps= 14 q=28.0 size=N/A time=00:00:03.58 bitrate=N/A dup=2 drop=0 speed=1.14x 19:23:58.895 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 57 fps= 16 q=28.0 size=N/A time=00:00:04.09 bitrate=N/A dup=2 drop=0 speed=1.11x 19:23:59.434 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 70 fps= 17 q=28.0 size=N/A time=00:00:04.73 bitrate=N/A dup=2 drop=0 speed=1.13x 19:23:59.916 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 82 fps= 17 q=28.0 size=N/A time=00:00:05.12 bitrate=N/A dup=2 drop=0 speed=1.09x 19:24:00.587 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 94 fps= 18 q=28.0 size=N/A time=00:00:05.63 bitrate=N/A dup=2 drop=0 speed=1.05x 19:24:01.111 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 111 fps= 19 q=28.0 size=N/A time=00:00:06.27 bitrate=N/A dup=2 drop=0 speed=1.07x 19:24:01.608 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 125 fps= 20 q=28.0 size=N/A time=00:00:06.91 bitrate=N/A dup=2 drop=0 speed=1.08x 19:24:01.754 c.g.o.c.FfmpegWatcher : 205 JVM 关闭中,正在清理 ffmpeg 进程... 19:24:01.855 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] 19:24:01.855 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] 19:24:01.855 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [q] command received. Exiting. 19:24:01.855 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] 19:24:01.891 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] frame= 175 fps= 26 q=-1.0 Lsize=N/A time=00:00:07.29 bitrate=N/A dup=2 drop=0 speed=1.09x 19:24:01.892 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] video:2412kB audio:24kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] frame I:2 Avg QP:15.71 size:227681 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] frame P:82 Avg QP:23.17 size: 23836 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] frame B:91 Avg QP:25.75 size: 652 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] consecutive B-frames: 1.7% 86.9% 0.0% 11.4% 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] mb I I16..4: 57.3% 18.7% 24.0% 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] mb P I16..4: 0.9% 0.9% 0.0% P16..4: 14.8% 1.3% 0.8% 0.0% 0.0% skip:81.2% 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] mb B I16..4: 0.0% 0.0% 0.0% B16..8: 0.6% 0.0% 0.0% direct: 0.6% skip:98.8% L0:29.5% L1:69.7% BI: 0.8% 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] 8x8 transform intra:31.1% inter:49.5% 19:24:01.893 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] coded y,uvDC,uvAC intra: 45.0% 11.2% 2.3% inter: 3.7% 0.9% 0.0% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] i16 v,h,dc,p: 64% 17% 13% 6% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 16% 28% 37% 4% 3% 2% 4% 3% 5% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23% 30% 8% 4% 3% 3% 4% 3% 23% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] i8c dc,h,v,p: 74% 14% 11% 1% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] Weighted P-Frames: Y:0.0% UV:0.0% 19:24:01.894 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [libx264 @ 000002f0a9d600c0] kb/s:2831.40 19:24:01.990 c.g.o.c.FfmpegWatcher : 152 [FFMPEG] [aac @ 000002f0a9c113c0] Qavg: 61755.230 19:24:02.052 c.g.o.c.FfmpegWatcher : 160 [FFMPEG] 日志读取线程结束,ffmpeg 进程已终止
可以看到,打印了正在执行文件夹的名称,同时在终止程序时,会清理相关进程,这样我们最后一个文件,虽然没有录制一分钟,但是会录制到程序停止时。
Java小强
未曾清贫难成人,不经打击老天真。
自古英雄出炼狱,从来富贵入凡尘。
发表评论: