HLSEmbeddingPlayer

如何在网站上嵌入 HLS 视频(iframe 与 hls.js)

手把手教你把 HLS 视频放到网页上:现成的 iframe 播放器、响应式代码、URL 参数,以及自行搭建 hls.js 播放。

HLS(HTTP Live Streaming)是如今大多数网站播放点播视频所用的格式。它不是一个巨大的 MP4 文件,而是用一个小小的文本播放列表来描述视频,列表指向同一视频的多个版本,每个版本都被切成短片段。播放器会提前下载几个片段,测量它们到达的速度,并随时在版本之间切换。使用手机网络的观众拿到轻量版本,使用光纤的观众看到清晰版本,而且没有人需要等整个文件下载完才能看到第一帧。

本指南介绍两种把 UFOLOAD 上的 HLS 视频放到你自己网页上的方法:一种是用 iframe 嵌入现成的播放器,大约一分钟就能完成;另一种是用 hls.js 驱动你自己的 <video> 元素,让你完全掌控页面。两者使用同一个视频流,所以你可以先用 iframe,以后再换成 hls.js,无需重新上传任何内容。

UFOLOAD 的 HLS 流是什么样的

文件上传后,转码器会用 H.264 视频和 AAC 立体声音频将其编码为一到四个版本,称为清晰度档位(rendition):360p、720p、1080p 和 2160p(4K)。档位绝不会超过源文件,因此上传 720p 的视频会生成 720p 和 360p,而不会放大成 1080p。你实际能获得的最高档位还取决于你的套餐,当前限制见价格页面。如果想全面了解档位是如何选定的,请阅读自适应码率阶梯详解。

每个档位都以普通 MP4 的形式存储,索引位于文件开头。观众开始播放时,存储层会即时把这些 MP4 文件封装成 HLS:主播放列表(master.m3u8)列出每个档位及其峰值带宽、分辨率和编解码器,而每个档位都有自己的播放列表,由四秒长的片段组成。关键帧的位置与片段边界对齐,正因如此,播放器才能在视频中途干净利落地切换画质。

播放列表和片段由缓存节点提供,并带有 Access-Control-Allow-Origin: * 响应头,因此运行在你域名上的播放器可以直接请求它们。每个 URL 都经过签名并带有过期时间,这一点在后面讨论 hls.js 方案时会很重要。

第 1 步:上传视频并等待就绪

你可以在控制面板中拖入文件或粘贴直链上传,也可以使用 FTP、WebDAV 或 API(curl、Python 和 Node.js 示例见通过 API 上传视频)。文件会依次经历 uploading、queued、processing 和 ready 这几个状态;failed 状态会附带原因,并可在控制面板中重试。短片几分钟内即可就绪,长片需要更久,付费套餐享有优先编码队列。

你不必等到页面完全做好。如果有人在文件仍在处理时打开播放器,播放器会显示带进度的处理提示,并在处理完成后自动切换到视频。不过,发布页面前还是要确认状态为 ready,以免页面上线后,最早的访客看到的只是一个进度条。

你需要视频的标识符。控制面板会在分享面板中显示它,API 则以 public_id 字段返回,这是一个 11 个字符的短代码。嵌入地址中填写的就是这个代码。

第 2 步:用 iframe 嵌入播放器

上传完成后,以及在每个视频的分享面板中,控制面板都会提供一段 iframe 代码,看起来就像下面第一段代码。将 VIDEO_ID 替换为你的视频标识符即可。播放器页面本身不会被搜索引擎收录,这正是嵌入所需要的:参与排名的是你的页面,而不是播放器框架。

控制面板提供的代码片段 · html
<iframe width="640" height="360"
  src="https://iframe.andromedans.live/e/VIDEO_ID"
  title="My video"
  frameborder="0"
  allow="autoplay; fullscreen; picture-in-picture"
  allowfullscreen></iframe>

固定的像素尺寸在手机上会出问题。要做响应式页面,可以把 iframe 包在一个保持 16:9 比例的容器里,让框架填满它。播放器会铺满整个框架,因此视频可以平滑缩放。

响应式嵌入 · html
<div style="position:relative;aspect-ratio:16/9;max-width:960px">
  <iframe src="https://iframe.andromedans.live/e/VIDEO_ID"
    title="My video"
    style="position:absolute;inset:0;width:100%;height:100%;border:0"
    loading="lazy"
    allow="autoplay; fullscreen; picture-in-picture"
    allowfullscreen></iframe>
</div>

可以添加到地址中的参数

  • autoplay=1 会在播放器加载后开始播放。大多数情况下浏览器会阻止带声音的自动播放,所以请配合 mute=1 使用。
  • mute=1 让视频以静音状态开始播放,观众可以随时取消静音。
  • loop=1 让视频在结束后从头重新播放。
  • t=30 从第 30 秒开始播放,便于用深层链接直接跳到长视频中的某个时刻。

地址中的参数总是优先于播放器工作室中的同名设置。播放器工作室适合设置全局默认值,例如皮肤、强调色、Logo 和按钮布局;当某个页面需要不同表现时,就使用参数。你甚至可以为每个嵌入域名保留单独的播放器配置文件。

提示

如果播放器提示不允许嵌入,很可能是你页面的域名不在允许嵌入的域名列表中。要了解这个列表如何工作,请参阅域名锁定与地区限制。

第 3 步(可选):用 hls.js 播放视频流

iframe 是最快捷的方式,但有时你需要自己的页面结构:自定义控制栏、放在轮播图里的视频、由你自己的代码发出的统计事件。这时你需要播放列表地址和一个播放器库。除 Safari 外,其他浏览器都无法原生播放 HLS,因此通常的选择是 hls.js,这是一个把 HLS 片段送入标准 <video> 元素的 JavaScript 库。Safari 和 iOS 原生支持 HLS,不需要它。

播放列表地址就是视频对象的 links.playback 字段。请在你的服务器上用 API 密钥请求它,因为密钥绝不能出现在浏览器代码中。同一个请求还会返回 links.expires_at;链接带签名且有时效,所以每次渲染页面时都要请求新链接,而不是把链接存进数据库。

服务器端(Node.js 18+):获取签名的播放列表链接 · js
const BASE = 'https://ufoload.com/api/v1'

export async function playbackUrl(fileId) {
  const res = await fetch(`${BASE}/files/${fileId}`, {
    headers: { Authorization: `Bearer ${process.env.UFOLOAD_API_KEY}` },
  })
  if (!res.ok) throw new Error(`UFOLOAD API: ${res.status}`)
  const { file, links } = await res.json()
  if (file.status !== 'ready') return null // still processing
  return links.playback // signed master.m3u8 URL
}

如果需要默认值以外的有效期,POST /files/{id}/links 接受 60 秒到 30 天之间的 ttl,还可以把链接绑定到 IP 地址或 Cookie。完整说明见 API 文档。另外还有一个无需密钥的公开端点 GET /api/v1/public/files/{id},观看页和嵌入页使用的就是它,其链接有效期为六小时。

在页面上创建播放器。下面的代码在支持的环境中使用 hls.js,在 Safari 上回退到原生播放,其他情况下显示一条简单的提示。请自行托管库文件或固定版本号,而不是总加载最新版。

客户端 · html
<video id="player" controls playsinline preload="metadata"
       poster="POSTER_URL" style="width:100%;aspect-ratio:16/9;background:#000"></video>
<script src="/vendor/hls.min.js"></script>
<script>
  const video = document.getElementById('player')
  const src = 'PLAYLIST_URL_FROM_YOUR_SERVER'

  if (window.Hls && Hls.isSupported()) {
    const hls = new Hls()
    hls.loadSource(src)
    hls.attachMedia(video)
    hls.on(Hls.Events.ERROR, (_, data) => {
      if (!data.fatal) return
      if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls.startLoad()
      else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls.recoverMediaError()
      else hls.destroy()
    })
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = src // Safari, iOS
  } else {
    video.outerHTML = '<p>This browser cannot play HLS video.</p>'
  }
</script>

视频对象还带有用作封面图的 links.poster,以及用于悬停预览缩略图的 links.sprite,如果你自己做进度条,可以用上它们。使用 hls.js 意味着放弃 UFOLOAD 播放器替你完成的那些功能:画质菜单、章节、字幕选择、Logo 叠加,以及在有广告可投放时显示的广告。这才是真正的取舍,下表做了总结。

iframe 还是 hls.js:该用哪个

问题iframe 播放器在你的页面上使用 hls.js
搭建时间一分钟,复制粘贴即可一小时或更久,另需一个小型服务器端点
播放器功能画质菜单、章节、字幕、悬停预览、Logo,以及有广告时的广告你自己做什么就有什么
变现有广告可投放时,广告会在播放器中展示并计数不可用,因为广告层位于 UFOLOAD 播放器中
样式在播放器工作室中设置皮肤、颜色、Logo 和按钮任意 HTML 和 CSS
链接过期自动处理每次渲染页面时都要请求新链接
域名锁定强制执行允许嵌入的域名列表不适用于你自己提供的链接,因此请使用较短的 TTL 并绑定 IP 或 Cookie

故障排查清单

  • 黑屏或一直转圈。 打开浏览器的网络面板,查找 master.m3u8。返回 403 说明链接已过期,或者观众被国家/地区或 IP 规则拦截;请请求新链接。
  • 在 HTTPS 页面上被浏览器拦截。 所有内容都必须走 HTTPS。切勿把 http:// 地址粘贴到 iframe 或 hls.js 中。
  • 自动播放没有反应。 浏览器会阻止带声音的自动播放。请添加 mute=1,或在 hls.js 中调用 play() 之前设置 video.muted = true。
  • 显示处理提示而不是视频。 文件尚未就绪。轮询 GET /files/{id},直到 status 变为 ready。
  • 只能播放低画质。 播放器起步较保守,测出吞吐量后会立即提升画质。你的套餐和源文件也会限制最高档位;请对照价格和功能页面。

页面跑通之后,你可能想防止盗链,或者在有广告可投放时从中获得收益。接下来的指南分别介绍了这两点:限制视频可被嵌入的位置和在播放器中投放广告,为你的视频网站变现。如果你还在考虑把视频托管在哪里,视频托管选择清单列出了需要比较的要点。

免费注册账号试一试

几分钟内上传视频,获得 HLS 播放器和 API 密钥。各套餐限制见价格页面。