长时间录屏中途崩溃:MP4 打不开的 6 种救回方案与参数设置

上周同事录一场 4 小时的产品评审会,录到第 3 小时 40 分,笔记本电源被保洁阿姨踢掉。录屏软件直接消失,桌上留下一个 3.7 GB 的 MP4。

双击,转两圈,"无法播放此文件",错误码 0xC00D36C4。她第一反应是重录,可那是已经开完的会。

文件最后被我救回来了,前后大概半小时。中间走了两个弯路:先装了三个号称"一键修复"的软件,差点把文件写得更烂;后来看到命令行报错,以为没戏,其实换条命令还能接着捞。

‌这类文件大多数能救,前提是别再对它反复折腾。 ‌ 能不能救,跟文件大小有关,跟录制时怎么设参有关,也跟"损坏"这两个字的严重程度有关。

一、MP4 到底坏在哪一块

三种常见的翻车方式

第一类是软件自己崩。录到第三、第四个小时,软件无响应或者闪退。连续高负载跑几个小时,内存和显存都在临界点上。

第二类是断电。笔记本电池耗尽、插头被拔、台式机跳闸。这是最彻底的一种,进程没有任何机会收尾。

第三类是写入中断。磁盘写满,或者外接硬盘掉线,数据流硬生生断在半路。

三种情况的共同结果是一样的:一个体积正常、却打不开的文件。

MP4 的内部结构,决定了这件事有多严重

MP4 由一个个"盒子"组成,最关键的两个是 moov 和 mdat。

moov 是索引,装着视频总时长、每条轨道的编码参数、每一帧在文件里的字节偏移、哪些帧是关键帧。mdat 是数据本体,画面和声音都在里面。

可以这么理解:moov 是目录,mdat 是正文。目录没了,书还在,但你不知道从哪一页开始读。

关键在于写入顺序。录制软件为了效率,会把 mdat 一路往后追加,moov 留到最后统一计算,因为时长、帧偏移这些数值只有全部录完才确定。正常停止录制,moov 写进文件尾部,播放器正常打开;中途中断,moov 缺失或者只写了一半,文件就打不开了。

这也是为什么同样被切断,MP4 比 MKV 脆弱得多。MKV 的结构信息可以边录边追加,中断时通常只丢最后几秒,容器本身仍然能打开。

花一分钟判断你的文件属于哪一类

别急着装工具,先做三步。

  1. 看文件大小。如果是 0 KB,说明录制还没真正开始写入,底层没有有效数据,可以放弃了。
  2. 用 VLC**试播。它能跳过损坏的帧继续读。如果能看到部分画面或者听到声音,说明 mdat 基本完好,后面的方案把握都比较大。
  3. 命令行执行 ffprobe broken.mp4。报 moov atom not found,就是索引丢了,重点看方案一和方案四。

这三步加起来不到一分钟。有个细节提醒一下:别用系统自带播放器反复双击测试。反复失败有时会触发播放器的错误缓存,反而干扰后面工具对文件结构的识别。

二、参数设置:崩溃后能救回多少,录之前就定了

很多人把参数当画质开关调,其实它们同时决定了另一件事:文件出问题时,你手里还剩多少可恢复的空间。

分辨率和帧率不要顶到硬件上限

1080p 加 30fps,够覆盖会议、网课、代码演示这些绝大多数场景。游戏高光可以上 60fps。一上来就 4K60,还用软编码,等于让编码器和磁盘连续满负荷跑几个小时,崩溃概率会明显上升。

码率控制:录制场景选 CQP

CBR 固定码率,每个时间片分配相同的数据量。它是给直播用的,平台需要稳定的码率输入。录制用 CBR,静态画面浪费掉大量码率,运动画面又不够用。

VBR 按画面复杂程度分配数据量,是录制里比较常规的选择。

CQP 或者 CRF 不设目标码率,让编码器按画面复杂度自己决定要用多少数据,录制场景里这个最合适。日常用 CQP 20 到 22。如果后期还要二次剪辑,调到 18,多留一点细节。

具体量级给个参考:1080p60 的内容,码率落在 12000 到 20000 Kbps 是比较稳的区间。要传到 B 站,站方建议平均码率 20000 Kbps,峰值不超过 60000 Kbps。

关键帧间隔,它决定崩溃后能救回多细

关键帧是完整画面,其他帧只记录与前一帧的差异。间隔调大,文件会小很多,代价是拖动进度条时的恢复变慢。

关键帧间隔 10 分钟文件体积 拖动进度条响应
30 帧 约 1.8 GB 即时
100 帧 约 1.2 GB 约半秒延迟
250 帧 约 800 MB 约两秒延迟

对长时间录制来说,关键帧间隔还有一层意义:它相当于可恢复的颗粒度。数据断在关键帧之间,那一段就只能整段丢掉。录制场景直接设 0,交给软件自动算;要手动设,别超过帧率的三倍。为了省空间把它调得很大,等于拿素材安全换硬盘容量。

编码器:长录优先硬件编码

NVENC、QSV、AMF 走的是显卡上的专用编码单元,CPU 占用低,发热也小。libx264 软编码画质可控,但连续跑几个小时,CPU 满载加上高温,本身就是崩溃的诱因。有独显就先试硬件编码,占用反而更低。

容器格式:录制用 MKV,交付再转 MP4

这是整篇最值得记的一条。

MP4 的 moov 必须等录制结束才能写入。MKV、FLV 这类容器可以边录边追加结构信息,突然中断通常只丢最后几秒,文件本身还能打开。

所以稳妥的做法是:录制阶段用 MKV,交付时无损重封装成 MP4。重封装只换外壳不重新编码,几秒完成,画质不变。要提醒一句,手动把 .mkv 改名成 .mp4 不算重封装,播放器依然不认。

用 OBS Studio**的话它自带这个功能。设置里勾上"自动重新封装录像",停止录制后直接产出 MP4,原始 MKV 也保留着。

几个容易被忽略的细节

  • 保存路径放固态盘,剩余空间留足 50 GB。写满即崩。
  • 电源计划改成高性能,把"在此时间后关闭硬盘"设成"从不"。默认策略在无操作时会降频、休眠硬盘,长录的时候就是隐患。
  • 录屏程序用管理员身份启动,加进杀毒软件白名单,免得被当成屏幕抓取行为拦截。
  • 长时间录制把预览窗口关掉,能省下持续的渲染开销。
  • 开启自动分段,每 30 到 60 分钟切一个文件。

三、六种救回方案

前两个是命令行手段,第三个是图形化路线,不想碰命令行的看这条。后三个解决的是"让下一次不再崩"。

方案一:FFmpeg 无损重封装,重建索引

适用:moov 还在,只是位置或顺序异常,或者结构有轻微损坏。

csharp 复制代码
bash
ffmpeg -i broken.mp4 -c copy -movflags +faststart fixed.mp4

FFmpeg**的 -c copy 表示只复制音视频流、不重新编码,所以是秒级完成、画质无损。-movflags +faststart 把 moov 挪到文件开头,播放器一打开就能读到元数据。

如果上面这条报错,按顺序再试这两条:

csharp 复制代码
bash
# 时间戳错乱、出现负时间戳导致无法播放
ffmpeg -i broken.mp4 -c copy -fflags +genpts -avoid_negative_ts make_zero fixed.mp4

# 中间有坏帧,忽略错误帧继续处理
ffmpeg -err_detect ignore_err -i broken.mp4 -c copy fixed.mp4

我实测过一个被截断的 MP4,第一条命令直接报 moov atom not found 退出。这说明 moov 是真的没了,重封装无能为力,得跳到方案四。这个报错本身,就是最好的分诊工具。

方案二:用 ffprobe 批量体检,别在没救的文件上耗时间

一次长录产生十几个分段,或者素材盘里堆了一堆文件的时候,先判断哪些值得动手。

python 复制代码
python
import json
import pathlib
import subprocess


def probe(path: pathlib.Path) -> dict:
    """用 ffprobe 读取文件结构,能正常返回就说明容器和索引可读。"""
    cmd = [
        "ffprobe", "-v", "error",
        "-print_format", "json",
        "-show_format", "-show_streams",
        str(path),
    ]
    r = subprocess.run(cmd, capture_output=True, text=True)
    if r.returncode != 0:
        tail = [ln for ln in r.stderr.strip().splitlines() if ln.strip()]
        return {"ok": False, "err": tail[-1] if tail else "unknown"}

    info = json.loads(r.stdout)
    fmt = info.get("format", {})
    return {
        "ok": True,
        "duration": float(fmt.get("duration", 0)),
        "size_mb": int(fmt.get("size", 0)) / 1024 / 1024,
        "types": [s.get("codec_type") for s in info.get("streams", [])],
    }


if __name__ == "__main__":
    here = pathlib.Path(__file__).parent
    files = sorted(here.glob("*.mp4"))
    if not files:
        print("当前目录下没有 mp4 文件")
    for f in files:
        res = probe(f)
        if res["ok"]:
            print(f"[可读] {f.name} | {res['duration']:.1f}s | "
                  f"{res['size_mb']:.1f}MB | 轨道={res['types']}")
        else:
            print(f"[待修] {f.name} | {f.stat().st_size / 1024 / 1024:.1f}MB | {res['err']}")

把脚本和视频放同一个目录跑,输出长这样:

kotlin 复制代码
text
[待修] broken.mp4 | 0.4MB | broken.mp4: Invalid data found when processing input
[可读] test.mp4 | 10.0s | 0.5MB | 轨道=['video', 'audio']

它会顺手把视频轨、音频轨是否齐全打出来。轨道信息对后面的判断有用:只有视频轨没有音频轨,说明音频那块写坏了;两条轨都在却打不开,基本就是索引问题。

方案三:嗨格式录屏大师,把"崩了之后"交给软件自己兜

不是每个人都愿意敲命令行。而且真正省事的思路,本来就不该等到崩溃之后再补救。

我用过一段时间这类图形化录屏软件,一开始就是图它对参数面板做得比较直白:分辨率、帧率、码率档位、编码器都能直接选,硬件加速走显卡的编码单元,CPU 占用比纯软编码低一截。它的长时间录制可以开自动分段,比如每 30 分钟拆一个文件,某一段出问题也只丢那一段。

真正减少损失的是异常中断后的处理。软件崩溃或者断电,重新启动后它会去识别本次录制的缓存文件,提示恢复未完成的录制,把已经落盘的部分导出成正常文件。这比事后从 mdat 里一点点刨数据省事,因为缓存维护发生在录制过程之中,而不是等文件坏了再补。

边界也得说清楚。这套机制依赖软件自己的缓存刷盘策略。如果断电真的发生在缓存还没写入磁盘的那一瞬间,最后几十秒到几分钟照样会丢。它的定位是降低损失,不是数据保险箱。所以就算用它,前面说的分段录制和 MKV 容器这两个习惯,我还是建议一并留着。

方案四:untrunc,moov 完全丢失时用同源文件重建

如果方案一已经判定 moov 缺失,就靠这个工具。

原理是拿一段同设备、同参数录出来的正常视频当模板,把它的 moov 结构套到损坏文件上,再按 mdat 里的实际数据重算每帧偏移。全程不重新编码,画质不变。

bash 复制代码
bash
# Ubuntu / Debian 上编译安装
sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev
git clone https://github.com/ponchio/untrunc.git
cd untrunc && make

# 修复:第一个参数是正常文件,第二个是损坏文件
./untrunc -v good.mp4 broken.mp4

跑完会在同目录生成 broken_fixed.mp4。Windows 用户可以直接下预编译包,里面带一个图形界面,填两个路径点一下就行,不用编译。

参考文件挑得好不好,直接决定成败,四个条件都得满足:

  1. 同一台设备、同一个软件版本录出来的
  2. 分辨率、帧率、编码格式一致
  3. 录制时间接近,保证编码器版本相同
  4. 文件扩展名一致

同设备场景下,公开统计的修复成功率在七成到九成之间;跨设备基本没戏。另外要有心理准备:修好的文件末尾可能出现黑屏或者时间轴轻微不准,因为原始文件的尾部本来就没写完,那是真实缺失,不是修复失败。

方案五:用 OBS 搭一套"崩得起"的录制流程

与其修,不如让文件不容易死。OBS 的路径是:设置 → 输出 → 输出模式切到"高级" → 录像标签页。

  • 录像格式选 MKV 或 FLV,别直接选 MP4。
  • 勾上"自动重新封装到 MP4",停止录制后自动产出 MP4,并保留原始 MKV。
  • 开启自动分段,按时间或者按大小切。课程、会议这类长录按时间更直观,30 到 60 分钟一段。
  • 编码器按显卡选 NVENC、QSV 或 AMF。
  • 关键帧间隔设 0,交给软件自动决定。
  • 输出分辨率跟显示器原生分辨率对齐,别再吃一次缩放运算。

再配合管理员权限启动、保存路径放固态盘、关掉录制预览,一整套下来长录稳定性会明显不一样。这些设置花五分钟,省下的可能是四个小时。

方案六:写个脚本,把重封装和巡检自动化

天天处理素材的话,可以把"录制停止"当成一个事件来处理:文件不再变大,判定录制结束,自动重封装并归档。

python 复制代码
python
import pathlib
import subprocess

SRC = pathlib.Path("rec")          # 录制目录,放 MKV
DST = pathlib.Path("exported")     # 导出目录,输出 MP4


def remux(mkv: pathlib.Path) -> tuple:
    """只换封装不重新编码,-c copy 保证画质无损。"""
    out = DST / f"{mkv.stem}.mp4"
    cmd = [
        "ffmpeg", "-y", "-v", "error", "-i", str(mkv),
        "-c", "copy", "-movflags", "+faststart", str(out),
    ]
    r = subprocess.run(cmd, capture_output=True, text=True)
    if r.returncode != 0:
        return False, r.stderr.strip()[-200:]
    return True, f"{out.stat().st_size / 1024 / 1024:.1f}MB"


if __name__ == "__main__":
    DST.mkdir(exist_ok=True)
    for f in sorted(SRC.glob("*.mkv")):
        ok, msg = remux(f)
        print(f"{f.name} -> {'完成 ' + msg if ok else '失败: ' + msg}")

想再往前一步,可以在录制期间加个看门狗:每隔几秒检查目标文件的修改时间,超过阈值(比如 60 秒)没更新就判定录制已经停止,立刻触发重封装,并发一条通知。无人值守的挂机录制里这个挺有用,人不在现场也能第一时间知道断了。

四、输出效果参考

手段 适用情况 恢复程度 耗时 是否损画质
FFmpeg 重封装 moov 存在但位置或顺序异常 通常完整恢复 几十秒到几分钟 否
ffprobe 体检脚本 批量判断文件可修性 不修文件,只做分类 数百个文件几分钟 不涉及
图形化工具缓存恢复 软件崩溃、断电后重启 通常能拿回绝大部分 取决于缓存落盘情况 否
untrunc 参考修复 moov 完全丢失 同设备约 70% 到 90% 10 分钟素材几分钟内 否,末尾可能异常
OBS 分段加自动重封装 预防,降低单次损失 单段损坏只丢一段 录制时自动完成 否
自动化脚本 无人值守、批量素材 取决于上游修复手段 后台运行 否

所有方案都建议先复制一份原文件再动手。修复工具写盘过程中出错,会把本来还能救的文件覆盖掉,这种损失不可逆。

五、局限和注意事项

  • 0 KB 文件没有修复价值。数据从没落盘,任何工具都变不出来。
  • mdat 大面积损坏救不回来。花屏、绿屏、大段丢帧,说明数据本体坏了,重封装和 untrunc 都帮不上忙。
  • 参考文件跨设备成功率很低。untrunc 的 moov 模板必须匹配编码参数,随手拿另一台电脑的视频顶替,基本白跑。
  • 修复后的文件不是原件。结尾黑屏、时长略有偏差都属于正常现象。
  • 磁盘坏道和文件系统错误要单独排查。同一个位置反复出问题,先跑一遍磁盘检测,否则修好的文件还是会在同样的位置卡住。
  • 在线修复服务有隐私成本。素材要传到别人的服务器,涉及内部会议、未公开内容时不要用。
  • 依赖软件自身缓存的方案,保护范围就到缓存刷盘那一刻为止。断电时间点不巧,最后一段照样丢。
  • 别在原始损坏文件上反复运行不同的修复工具。每个工具都可能改写原文件,一次试坏,后面连备份都没有。

六、FAQ

‌Q1:文件大小正常,双击就是打不开,一定是 moov 丢了吗? ‌

大概率是。MP4 打不开最常见的两种结构问题,一个是 moov 缺失,一个是 moov 在文件末尾没前置。前者靠 untrunc,后者靠 FFmpeg 重封装加 +faststart。跑一条 ffprobe 就能确认,不用猜。

‌Q2:录屏软件为什么非要用这种"会崩"的格式? ‌

为了方便。MP4 兼容性最好,剪辑软件、上传平台、手机播放全都认。问题不在格式本身,而在于很多软件默认把 moov 放到最后写。把容器换成 MKV 再重封装,就绕开了这个设计。

‌Q3:只有一段损坏的视频,没有同设备的正常文件,还能修吗? ‌

能试的还有两条路。一是 FFmpeg 重封装那几条命令,有时结构只是轻微异常就能救回来。二是 recover_mp4**这类直接从 mdat 里抠可播放片段的工具,它不需要参考文件,代价是结果不保证完整,可能只能拿到部分画面。

‌Q4:修好的文件时长不对、结尾黑屏,是不是等于修复失败? ‌

不算。原始文件尾部数据本来就没写进去,修复工具只能基于现有数据重建。判断修复成功的标准是三条:能正常打开、进度条能拖完、中间画面和声音对得上。满足就算救回来了。

‌Q5:用 MKV 录,剪辑软件不认怎么办? ‌

重封装成 MP4 就行。这一步只换外壳,不是转码,画质不变,几秒钟完成。注意别手动改扩展名,那不会重组内部结构,软件照样读不了。

‌Q6:为什么录到一半会崩? ‌

常见的原因有五个:参数顶到硬件上限(4K60 加软编码);磁盘写满或者写入掉速;后台程序抢占 CPU、显存和音频设备;系统的硬盘休眠和降频策略;显卡驱动版本太旧。

‌Q7:分段录制会伤画质吗? ‌

不会。分段只是把文件切开,每段的编码参数完全一致。唯一的影响是段与段之间的帧不连续,剪辑时接缝处可能要单独处理一下。

‌Q8:断电和软件崩溃,处理方式一样吗? ‌

判断步骤一样,都是先看大小再跑 ffprobe。区别在概率。断电更容易造成 moov 完全缺失,这种情况直接上 untrunc 更省时间;软件崩溃时 moov 有时候已经写进去了,先试 FFmpeg 重封装,说不定一条命令就解决。

七、总结:按顺序做,别乱试

  1. 崩了先别动原文件,复制一份出来操作。
  2. 看文件大小,0 KB 的直接放弃。
  3. ffprobe 判断 moov 是否还在。
  4. 在,就用 FFmpeg 重封装;不在,就用 untrunc 配同源参考文件。
  5. 修完检查三件事:能打开、时长合理、音画同步。
  6. 下一次录制前把参数改掉:MKV 容器、自动分段、硬件编码、关闭硬盘休眠、路径放固态盘。
相关推荐
code_Bo39 分钟前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
kyriewen1 小时前
AI 能把页面写出来,为什么改个需求就开始崩?
前端·javascript·人工智能
涛涛ing2 小时前
2026年最值得关注的前端变化,藏在“默认值”里
前端
亿元程序员4 小时前
太牛了!这AI做出来的游戏,居然还能变现!
前端
hellice4 小时前
闪传 FlashDrop 实战:我用 300 行 Node 代码做了个「4 位取件码」临时文件中转站
前端·产品
用户0829773260054 小时前
RTX 5500 MIG 踩坑记录:切分之后模型跑不起来,排错整整一下午
前端
Lank_M4 小时前
AI 放大后的图更清楚,但它不能当原图入库
前端
Swot4 小时前
SvelteKit 数据流研究:`+page.js` 和 `+page.server.js` 到底谁在跑,数据又去了哪儿
前端·后端
用户4147679304154 小时前
Windows 触摸屏上 Swiper 轮播滑不动?可能是内部滚动容器抢走了你的手势
前端