如何将 Base64 解码为 MP4
- 把 Base64 粘贴到 Base64 或 data URI。
data:video/mp4;base64,前缀可以保留。长字符串请使用 打开 .txt 文件;超过 4 MB 的内容会直接解码,不在文本框中显示。 - 播放器会加载视频。浏览器读取索引后会显示 时长 和 尺寸,示例视频为
0:02.0和96 × 64 px。 - 查看提示区域:如果是真正的 MP4,这里为空,否则会给出实际格式。
- 点击 下载文件。
解码和播放都在你的浏览器中进行;除 Cloudflare 的浏览量统计外,页面不允许发出网络请求。
MP4、MOV、M4A:同一种结构,多种格式
MP4 文件由一个个 box 组成,第一个 box ftyp 中保存着品牌标识(brand),说明文件遵循的是该格式的哪个变体。工具会读取这个品牌标识:
ftyp 中的品牌 | 识别为 | 本页的提示 |
|---|---|---|
isom、mp41、mp42、avc1、iso6 及其他大多数 | MP4 | 无 |
qt | MOV(QuickTime) | “这看起来是 MOV,而不是 MP4。”,附带 下载为 .mov |
M4A | M4A | “这看起来是 M4A,而不是 MP4。”:只有音频 |
3gp4、3gp5 及其他 3g 品牌 | 3GP,老式手机视频 | “这看起来是 3GP,而不是 MP4。” |
heic、mif1、avif | HEIC、AVIF | “这看起来是 HEIC,而不是 MP4。”:使用相同 box 结构的静态图片 |
品牌标识为 MP4 的文件也可能只有声音。它可以播放,尺寸 会显示 仅音频。以“MP4”名义发来的 WebM 文件会提示“这看起来是 WebM,而不是 MP4。”
索引的位置,以及它对损坏文件的影响
每个 MP4 都有一个 moov box,这是告诉播放器每一帧在哪里的索引。很多编码器(包括 ffmpeg)默认把它写在文件末尾,位于 mdat 中的媒体数据之后。使用 -movflags +faststart 时,ffmpeg 会把它移到文件开头,这样在整个文件到达之前就可以开始流式播放。
在本页,整个文件都在内存中,所以对于完整的视频,索引位置无关紧要。但如果 Base64 被日志、数据库字段或消息队列的大小限制截断了,位置就很重要:
- 索引在末尾: 截断会把索引切掉,什么都放不了。工具仍会识别为 MP4,因为开头的字节是完整的,播放器则提示“无法播放”,时长 显示为“不适用”。
- 索引在开头: 浏览器能读到索引,显示完整的时长,一直播放到数据用完为止。
所以,如果长视频失败而短视频正常,在怪罪编解码器之前,先把解码后的大小与原始大小对比一下。
用 Python 查看 box 结构
box 的布局很简单,不用任何库就能遍历:四个字节的大小、四个字节的类型,然后是内容。下面的代码列出顶层 box 和品牌标识:
import base64, struct
def mp4_boxes(data):
pos = 0
while pos + 8 <= len(data):
size, kind = struct.unpack(">I4s", data[pos:pos + 8])
if size == 1:
size = struct.unpack(">Q", data[pos + 8:pos + 16])[0]
elif size == 0:
size = len(data) - pos
yield kind.decode("latin-1"), pos, size
if size < 8:
break
pos += size
with open("clip.b64") as f:
data = base64.b64decode(f.read())
for kind, pos, size in mp4_boxes(data):
print(kind, pos, size)
if kind == "ftyp":
body = data[pos + 8:pos + size]
brands = [body[i:i + 4].decode("latin-1") for i in range(8, len(body), 4)]
print(" major:", body[:4].decode("latin-1"), "compatible:", brands)
对于 ffmpeg 生成的 H.264 视频,它会输出 ftyp 0 32,主品牌为 isom,然后是 free、mdat,最后是 moov。moov 位于 mdat 之前表示启用了 faststart;出现 moof box 表示这是分片 MP4,流媒体以及本页的示例都是这种。如果列表中没有 moov,说明文件不完整。
各浏览器对编解码器的支持情况见 Base64 转视频。要编码视频,请使用 MP4 转 Base64;Python 中的 Base64 介绍了如何解码大型输入。
常见问题
怎么把 Base64 转换成 MP4 文件?
把字符串粘贴到上方,在播放器中确认视频后点击 下载文件。视频会保存为 decoded.mp4,与当初编码的字节完全一致。
明明是 MP4,为什么提示“无法播放”?
要么里面的编解码器是你的浏览器不支持的,最常见的是 HEVC;要么文件不完整,丢失了索引。对下载的文件运行 ffprobe 可以区分这两种情况:它会给出编解码器名称,或者报告找不到 moov atom。
MOV 应该保存为 .mp4 吗?
请使用 下载为 .mov,即与内容相符的扩展名。MOV 和 MP4 的结构大部分相同,所以实际上改名往往也能用,但有些播放器会检查品牌标识,遇到不匹配就拒绝播放。