# GIF 转 MP4

每一帧都带着 GIF 给它的延时，变成 MP4 里的 H.264。在你的机器上转，文件从不上传。

> 在浏览器里把动态 GIF 变成 MP4，体积只剩零头。每一帧保留 GIF 自己的时间，不做重采样。MP4 里的 H.264，每个平台都收的文件。什么都不上传。

This is an interactive browser tool at https://httcup.github.io/tools/gif-to-mp4/. Files are processed on the device running that browser. Any deliberate sharing or optional network feature is described on the page. What follows is its written explanation; open the address to use it.

## Your GIF are **processed in your browser**. No processing upload.

你选的那个 GIF，解码、一帧一帧画出来、编码、写进 MP4，全都在这台机器的内存里完成，用的是你自己浏览器里的编码器，和从这个地址发来的代码。这里根本没有能做上传的东西，这一页的另一头也没有服务器可以接收。

- ✗ 不上传
- ✗ 不注册
- ✓ 断网可用
- ✓ 开源
- ✓ 文件留在你的设备上

## 怎么把 GIF 转成 MP4

1. **选那个 GIF。** 一次一个。浏览器直接从你的硬盘读它，页面会说它是什么：多大、多少帧、播多久、多少像素。
2. **读那一行说明。** 一行：尺寸、帧数和它们的时间、时长、码率。没有什么要设的，除非 GIF 有透明的地方，那时会出现一个颜色框，问那里填什么。
3. **转换，然后读那句写着「已核对」的话。** 每一帧画出来再编码，进度条会说到哪了。然后做好的文件会在这里重新打开，它必须跟 GIF 播得一样久，每一帧都在。它在下载按钮下面从内存里循环播放，你能看到接缝。

## The longer version

[如何把 GIF 转为 MP4，为什么会小得多](https://httcup.github.io/tools/guides/convert-a-gif-to-mp4/): 为什么同一动画的 MP4 只有 GIF 的十分之一，视频缺少哪些 GIF 能力，为什么时序易错，以及如何在浏览器中无需上传地转换。

## Also in the box

- [视频转 GIF](https://httcup.github.io/tools/video-to-gif/): 挑好段落、尺寸和帧率。
- [GIF 制作](https://httcup.github.io/tools/gif-maker/): 把一组图片变成一段动画。
- [GIF 拆帧](https://httcup.github.io/tools/split-gif/): 每一帧都单独存成一张 PNG。
- [GIF 分析](https://httcup.github.io/tools/gif-analyzer/): 帧、延时、调色板，以及每个字节的去向。

## Questions

### 为什么 MP4 小这么多？

因为 GIF 把每一帧都当成一张最多 256 色的图存起来，也不记得上一帧长什么样，而视频编码只存变化的部分。H.264 干这件事已经练了三十年。同一段动画通常出来只有十分之一大，常常更小，看起来还更好，因为它不再被限制在 256 种颜色，也不用再靠抖动来掩盖这一点。很小的 GIF，或者几乎不动的 GIF，转成视频可能反而变大；发生的时候页面会说。

### 时间会一样吗？

一样，一帧不差。GIF 没有帧率，只有每一帧各自的延时，视频把每一个延时原样保留：GIF 的每一帧就是视频的一帧，停的时间一模一样。不重采样，不翻倍，不丢帧。唯一的一点自作主张是每个浏览器都会做的那一点，不到两百分之一秒的延时按十来播，所以视频的时长跟 GIF 在浏览器里播的一样。做好的文件会重新打开核对这两点。

### 它会循环吗？

这由播放它的东西决定。GIF 自带循环的指令；MP4 没有这种东西，由播放器决定。大多数信息流和聊天软件会循环播放短视频，这一页的预览也循环，好让你看到接缝。桌面上的视频播放器通常只播一遍。

### 透明的地方怎么办？

会填一种颜色，因为视频是一整块实心的矩形。GIF 有透明的地方时，页面会显示一个颜色框，默认白色，因为大多数网页是白的；没有透明的地方就不显示。颜色在编码之前画在帧的底下，所以它是画面的一部分。

### 它会改画面尺寸吗？

H.264 要求偶数边，所以奇数宽度或高度会增加一行背景色，不进行重采样。如果最长边超过3840像素，GIF 会缩小到这个上限。页面会在开始前显示实际输出尺寸。缩小输出不会减小源画面的合成缓冲区。

### 要多久？

普通 GIF 使用硬件编码通常只需几秒，没有硬件编码会更久。进度条显示当前帧。取消会弃置编码器和输出，但原生支持检查、读取或同步绘制仍可能完成。迟到的任务不会替换较新的源文件或结果。

### 我的 GIF 会被上传到哪里吗？

不会。GIF 由你自己的浏览器在你自己的硬件上读取、解码、编码、写出，这一页的 `Content-Security-Policy` 列出了它可以联系的每一个地址，没有一个属于本站。最简单的自证办法是断开网络照样用。

### 手机上能用吗？

浏览器能编码视频的手机上能用，而且手机自带的硬件编码器很快。手机缺的是内存：GIF 的帧要先解码到内存里，所以很长的一个可能超出手机能装下的量。

### 有大小限制吗？要钱吗？

读取器最多保留5.12亿个已解码的局部图像像素，转换会拒绝已知缓冲区估算总量超过512 MiB的任务。这不保证编解码器内部内存或浏览器所有分配的上限。页面会说明拒绝原因。工具免费，无需账号、登录或试用期。广告维持网站运行，不会收到有关你的 GIF 的信息。

### 断网能用吗？

能。把页面加载一次，然后断开网络，它照样能用。这也是证明什么都没被上传的最简单的办法：一个把你的 GIF 发出去转换的工具，你一拔网线它就停了。

## How the privacy claim is verifiable

- **为什么 MP4 只有十分之一大，为什么每个平台都更想要它。** GIF 把每一帧都当成一张图存起来，最多 256 种颜色，也不知道上一帧长什么样。视频编码存的是变化的部分，全彩，而且 H.264 干这件事已经练了三十年；同一段动画出来只有十分之一大，常常更小，看起来还更好。这就是为什么每一个社交平台、聊天软件和内容系统要么拒绝大 GIF，要么在上传时悄悄把它变成 MP4，也是为什么当什么地方说「GIF 太大」的时候，它想要的从来都是那个 MP4。
- **上传才是最慢的那一步，而这一步在这里不会发生。** 每一个在线转换器都要先把文件拿到手：30 MB 沿着你的网络传上去，为的是换 3 MB 传回来，这还没算谁留着那份文件的问题。这一页用从这个地址发来的代码读 GIF，用你浏览器里本来就有的编码器写 MP4，所以唯一在动的字节，是从你的硬盘到内存再回去。这一页的 `Content-Security-Policy` 列出了它可以联系的每一个地址，没有一个属于本站，而且断了网它照样能用。
- **时间一帧一帧地保留，这一点大多数转换器都做错了。** GIF 没有帧率。每一帧自己说要停多久，而且各不相同：幻灯片式的 GIF 一张图停两秒，然后一口气翻十张。一个挑一个帧率再重采样的转换器会把有些帧翻倍、有些帧扔掉，幻灯片出来就一顿一顿的或者变短了。这里 GIF 的每一帧就是视频的一帧，时长正好是它的延时。唯一的一点自作主张，是每个浏览器都会做的那一点：不到两百分之一秒的延时按十来播。做好的文件会重新打开，数一遍每一帧都在，而且播放时长跟 GIF 一样。
- **视频做不到、GIF 做得到的两件事，事先说清。** GIF 可以让底下的东西透出来；视频是一整块实心的矩形。GIF 透明的地方得填一种颜色，页面会问填哪种，只在 GIF 确实有透明的地方时才问，默认白色，因为大多数网页是白的。还有，GIF 自带循环的指令；MP4 没有，视频循环不循环由播放它的东西决定。大多数信息流和聊天软件会循环播放短视频。这里的预览会循环，好让你看到接缝。
- **它在你机器上的代价，如实说。** 普通 GIF 使用硬件编码通常只需几秒，软件编码可能更久。读取器最多保留5.12亿个已解码的局部图像像素。转换还会拒绝已知缓冲区估算总量超过512 MiB的任务，包括保留的输入、整屏合成、恢复副本和收集的视频数据。编解码器内部还可能占用更多内存。取消会弃置任务，但原生读取或同步绘制仍可能完成。
- **Google 加载了什么，又没拿到什么。** 广告和统计脚本来自 Google。它们都拿不到任何关于你 GIF 的东西：没有文件、没有一帧画面、没有文件名、大小或时长。每一行读取、编码或写出它的代码都从这个源发出，并列在代码仓库里。
- **打赏按钮加载了什么，又没拿到什么。** 顶部的「Buy me a coffee」按钮由 cdnjs.buymeacoffee.com 的一个脚本画出来，字体来自 Google Fonts。它只是一个链接，不多不少：它不上报访问，也拿不到任何关于你或你 GIF 的东西。除非你点它，否则什么都不会发生，点了以后去的是别人的网站。
- **断网也能用。** 断开网络，这一页上的所有东西照常工作。这是最简单的证明：一个把你的 GIF 发出去转换的工具会停下来。

**Check it yourself.** None of the above has to be taken on trust. This page is generated from the templates and config in the repository by a build script you can read and run yourself, and the result is committed to the `dist` branch — so you can diff what is served against what a build of the sources produces: https://github.com/httcup/tools

The files worth reading first are `config/site.toml` for the Content-Security-Policy，GIF 的延时是怎么变成视频的时间的，看 `src/plan.js`；画帧和编码看 `src/encode.js`；读取器看 `src/shared/gif-decode.js`。这几个都够不着网络，旁边负责写的部分也一样。
