在浏览器里直接播放 S3 视频:presigned URL 播放指南

在浏览器里直接播放 S3 视频:presigned URL 播放指南
你把一个渲染好的视频上传到了 Amazon S3 存储桶——或者某个兼容 S3 的存储,比如 Cloudflare R2、Backblaze B2、MinIO、Wasabi。存储桶是私有的,本就该如此。现在你只想把这个视频看一眼,或者发给同事一个一点就能播的链接,而不必让对方去装 AWS CLI、也不用在控制台里翻来翻去。
有一种干净的做法,既不用下载文件、也不用把存储桶设成公开:用一个 presigned URL,丢进一个浏览器原生的播放器里。本文会讲清楚 presigned URL 到底是什么、怎么从它出发在浏览器里直接播放 S3 视频,以及那条唯一决定它能不能播的铁律——格式。
presigned URL 到底是什么
presigned URL 是在不放松存储桶权限的前提下,播放私有 S3 内容的那把钥匙。它就是一个指向某个对象的普通 HTTPS 链接,只不过在查询字符串里嵌入了一个临时的、经过密码学签名的令牌。这个签名实际上是在说:「谁拿着这个链接,谁就能读这个特定对象,直到它过期为止。」
有两个特性让它非常适合视频播放:
- 有时效。 过期时间由你设定——几分钟、几小时、几天都行。过了点,链接就失效了。你不是在创建永久的公开访问,而是在发一张临时通行证。
- 限定对象。 它只授予对那一个对象的访问权,而不是整个存储桶。你其他的文件依旧私有。
你可以用 AWS SDK、CLI(aws s3 presign s3://your-bucket/video.mp4 --expires-in 3600)或你所用服务商的对应工具生成它。生成结果是一条很长的、以签名参数结尾的 URL。一个浏览器原生的播放器要拉取并播放这个对象,需要的就只是这条 URL——浏览器里不需要 AWS 凭证,也不需要公开存储桶。
为什么浏览器能直接播它
下面这点是让整件事毫不费力的关键:对浏览器来说,presigned URL 不过是一条通过 HTTPS 返回视频字节的 URL。而现代浏览器本身就是视频播放器。Chrome、Edge、Safari、Firefox 都能原生解码 H.264 和 AAC,还带硬件加速,并能直接播放 MP4、WebM 和 HLS 流。
所以,只要 presigned URL 背后的对象是浏览器原生支持的格式,就没有任何东西需要转换、转码或下载。你把 URL 交给播放器,播放器向 S3 请求字节,浏览器的视频引擎就把它们播出来。文件始终留在你的存储桶里,只有视频流抵达你的标签页。这正是我们在 URL 直链播放指南 里深入讲过的同一种直链播放模式——S3 的 presigned URL 不过是它一个表现良好的来源而已。
关键在于,中间没有任何东西被重新上传到某个转换服务。presigned URL 指向的是你自己的 S3 对象;播放器只是从那里读取。你的视频不会被复制到某个第三方主机上去观看。
如何从 presigned URL 播放 S3 视频
- 生成 presigned URL。 用 AWS CLI、SDK,或你所用的兼容 S3 服务商的工具。设一个合理的过期时间——长到够看完,短到足够安全。(例如:
aws s3 presign s3://my-bucket/clip.mp4 --expires-in 3600。) - 打开播放器。 进入在线视频播放器。
- 粘贴 URL。 把完整的 presigned URL——连同签名参数一起——粘进 URL 输入框。
- 播放。 只要对象是浏览器原生格式,它就会立刻在原文件上串流播放,无需下载。
要分享的话,把同一个 presigned URL 和播放器链接发给同事即可;他们粘贴就能看,自己那边完全不需要 AWS 访问权限。当 URL 过期时,链接就单纯地停止工作了——访问权限会自行收回。
还有一个不大但确实存在、值得做对的小坑:生成 URL 时,确认对象存储时的 Content-Type 是正确的(比如 video/mp4)。如果 S3 把你的 MP4 当成 application/octet-stream 或 binary/octet-stream 来返回,一些浏览器会搞不清自己收到的到底是什么。上传时设好正确的 content type,就能保证内联播放顺畅。
S3 直链串流 vs. 其他做法
| 做法 | 下载对象 | 把存储桶设为公开 | presigned URL + 浏览器播放器 |
|---|---|---|---|
| 开始观看的时间 | 整个文件下载完之后 | 即时 | 原生格式下即时 |
| 存储桶保持私有? | 是 | 否——暴露给全世界 | 是——限定范围、临时访问 |
| 本地残留副本? | 有,留在磁盘上 | 无 | 无——原地串流 |
| 重新上传到某主机? | 不适用 | 不适用 | 否——直接读取你的 S3 对象 |
| 不用 AWS 也能分享? | 发文件(巨大) | 发链接(但是公开的) | 发链接(私有、会过期) |
presigned URL 正好命中那个甜蜜点:即时播放、存储桶私有、访问会过期、什么都不下载、什么都不重新托管。
诚实的边界:仅限原生格式
得说精确点,因为这正是「任何 S3 视频都能串流」这类宣传容易过度承诺的地方。
直链播放意味着是浏览器在解码这条流。这对浏览器原生支持的格式有效:
- MP4 / H.264(AAC 音频): 哪儿都能播。S3 托管视频最靠谱的选择。
- WebM(VP8/VP9): 支持面很广。
- HLS(
.m3u8): 在受支持的地方能播——如果你在存储桶里打包了自适应流,会很方便。 - MP4 里的 HEVC / H.265: 在较新且有硬件支持的 Chrome、Edge、Safari 上可用;在别处就没那么普遍了。
它不会播放浏览器无法解码的格式。如果你的 S3 对象是 MKV 容器,或用了某种冷门编码,浏览器就没有任何东西能把它渲染出来,而且这套流程里也没有哪个服务器在背后悄悄替你转码。这是有意为之的:这里的价值在于直接读取你的私有对象、原封不动地播放它,而不是把它丢进一个转换工厂里跑一遍。
所以,如果你需要看一个非原生的 S3 对象,诚实的路子是:把它下载到自己的机器上,用一个能解码该格式的本地播放器播放。(如果你宁愿在浏览器里本地解码、也不想装桌面软件,页面内的播放器和 URL 播放指南 能以完整的格式支持处理本地文件——那是一种独立于串流远端 URL 的模式。)更好的做法是,对于你打算用来串流的视频,一开始就在存储桶里存一份 MP4/H.264 版本;它哪儿都能播,毫无摩擦。
再补两条实用提醒。第一,原画质串流需要一条真正给力的网络连接——一个满码率的 4K 对象在弱网下会卡顿;这是播放源文件、而非播放降采样代理文件所要付的代价。第二,留意你的过期时间:如果链接在看到一半时失效了,对象并没有消失,过期的是那个令牌——用一个更长的时间窗重新生成 URL 即可。
常见问题
我必须把 S3 存储桶设成公开吗? 不必。presigned URL 授予的是临时的、限定对象的读取访问权,与此同时你的存储桶保持私有。这正是用它的全部理由。
我的视频会被上传到某个第三方服务器吗? 不会。presigned URL 指向的是你自己的 S3 对象;播放器从那里读取,并在你的浏览器里播放。没有任何东西被重新上传到某个转换主机。
我的 MKV 文件为什么无法从 URL 播放? 浏览器不原生支持 MKV 容器,而这套流程里也没有任何幕后转码。把它下载下来本地播放,或者改在存储桶里存一份 MP4 版本。
我的 MP4 无法内联播放——哪里出问题了?
最常见的原因是对象的 Content-Type 不对。确认它是以 video/mp4 返回的(上传时设好),而不是某种通用的二进制类型。
这对 R2、B2、MinIO、Wasabi 也适用吗? 适用。任何能签发 presigned(已签名)URL 的兼容 S3 存储,工作方式都一样——播放器需要的只是一条能返回视频字节的 URL。
URL 过期之后会怎样? 链接停止工作——访问权限会自动收回。重新生成一个新的 presigned URL 就能再次观看。
结语
presigned URL 加上一个浏览器原生的播放器,是观看 S3 视频最干净的方式:在原文件上即时播放、存储桶保持私有、访问按你设定的时间过期,整个过程中没有任何东西被下载或重新托管——前提是这个对象是浏览器能解码的格式。其余情况,要么下载下来本地播放,要么一开始就在存储桶里存一份 MP4。这就是那条诚实的边界,而对 S3 视频来说,绕着它来设计是件很容易的事。