基于OSS构建HLS流

OSS支持以RTMP协议推流音视频至存储空间(Bucket),并转储为HLS协议格式,同时提供了丰富的鉴权、授权机制实现更细颗粒度的音视频数据访问控制。

前提条件

已创建了存储空间。具体操作,请参见控制台创建存储空间

基础操作

OSS支持使用RTMP推流协议上传H264格式的视频数据和AAC格式的音频数据,并通过访问PlayURL地址的方式获取音视频数据。

  • 上传音视频数据

    1. 调用PutLiveChannel接口创建LiveChannel。

      调用该接口会返回RTMP推流地址PublishURL和播放地址PlayURL。您还可以使用SDK的方式创建LiveChannel。更多信息,请参见LiveChannel管理

    2. 通过PublishURL推流音视频文件。

      OSS将上传的音视频文件按HLS协议转储,即转储为一个m3u8格式的索引文件和多个ts格式的视频文件。具体操作,请参见RTMP推流上传

  • 获取音视频数据

    您可以通过浏览器直接访问PlayURL地址的方式,即访问m3u8索引文件的方式来获取音视频数据。

    Android和iOS等移动平台,以及PC端的少数浏览器例如Microsoft Edge和Safari,支持通过访问m3u8文件的方式播放视频。Chrome等浏览器需要嵌入Video.js等JavaScript脚本才能正常播放视频。

您在公共读写的Bucket中通过OSS上传和获取音视频,意味着任何人都有权限读写您的音视频数据,从而造成不必要的数据泄露和流量计费等问题。默认情况下,OSS Bucket的访问权限为私有,且拒绝任何来源的跨域请求。推荐您根据自身的使用场景,结合跨域资源共享CORS、防盗链、私有Bucket签名机制中的一种或多种方式,从而有效保护您的数据安全。

跨域资源共享CORS

如果不是通过浏览器直接访问OSS的音视频,而是先访问第三方的网页并在网页中嵌入了OSS的音视频,则很有可能遇到跨域问题,导致视频无法播放。这是因为当Web服务器和OSS不属于同一个域时,将违反同源策略,浏览器默认会拒绝该连接。

例如,Web服务器地址为http://192.168.xx.xx:8080,浏览器访问该地址获取了网页,网页的JavaScript脚本里嵌入了视频,视频来源指向OSS Bucket。此时,浏览器需要再次向OSS发送请求,试图访问OSS中的视频数据。但是,浏览器识别到OSS Bucket的访问地址与http://192.168.xx.xx:8080的网页地址不属于同一个域,则会先向OSS Bucket询问是否允许跨域请求。OSS Bucket默认不开启CORS配置,因此会拒绝浏览器的跨域请求,使得浏览器不能正常播放音视频。如下图所示:video

您可以通过OSS的跨域资源共享,解决因跨域限制导致音视频无法正常播放的问题。

  1. 登录OSS管理控制台

  2. 单击Bucket列表,之后单击目标Bucket名称。

  3. 单击数据安全 > 跨域设置

  4. 单击创建规则

  5. 创建跨域规则页面配置各项参数。

    结合本文档示例场景,请将来源设置为http://192.168.xx.xx:8080,其他参数设置请参见设置跨域资源共享

    • 如果来源为具体的域名,请填写完整的域名,例如www.example.com,不可省略为example.com

    • 如果来源为精准的IP地址,请填写包括协议类型和端口号在内的完整的IP地址,例如http://xx.xx.xx.xx:80,不可省略为xx.xx.xx.xx

    浏览器对跨域配置通常会有数十秒至几分钟的缓存时间。如果希望跨域配置立即生效,建议清空浏览器缓存后刷新网页。

防盗链

CORS规则可以有效阻止其他网站服务器在网页中嵌入您的音视频资源。但如果您通过直接访问OSS Bucket的方式获取音视频,则CORS规则将失效。在这种情况下,您可以通过OSS防盗链对Bucket设置Referer白名单的机制,避免其他人盗取您的音视频资源。

默认情况下,Bucket允许空Referer,通过本地浏览器访问PlayURL的方式可以直接观看视频。为了防止音视频资源被其他人盗用,您可以将Bucket设置为不允许空Referer,并将您信任的域名或IP加入Referer白名单。此时,除Referer白名单以外的第三方访问音视频资源时均会被拒绝,并返回403 Forbidden错误。

  1. 登录OSS管理控制台

  2. 单击Bucket列表,之后单击目标Bucket名称。

  3. 在左侧导航栏,选择数据安全>防盗链

  4. 防盗链页面,打开防盗链开关。

    • Referer框中,填写域名或IP地址,例如*.aliyun.com

      您可以结合实际使用场景设置不同的Referer字段。Referer配置示例详情请参见设置防盗链

    • 空Referer框中,选择不允许空Referer。

      说明
      • 选择不允许空Referer且设置了Referer白名单,则只有HTTP或HTTPS header中包含Referer字段的请求才能访问OSS资源。

      • 选择不允许空Referer但未设置Referer白名单,效果等同于允许空Referer,即防盗链设置无效。

  5. 单击保存

私有Bucket签名机制

为了保护您的数据安全,OSS默认Bucket的读写权限为私有。因此当您需要向私有Bucket执行读取或写入操作时,需要使用签名机制向OSS声明您的操作权限。

当您向私有Bucket推流时,需要对推流地址进行签名后才能上传音视频文件。具体操作,请参见RTMP推流地址及签名

使用Python SDK获取签名的推流地址示例如下:

说明

示例返回值为字符串形式格式如下:

rtmp://xxx.oss-cn-beijing.aliyuncs.com/live/xxx?playlistName=xxx&OSSAccessKeyId=xxx&Expires=xxx&Signature=xxx

最后Signature的值为签名,前面的为视频流的相关信息。

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# 创建并配置流频道。
# 该索引文件包含3个ts文件,每个ts文件的时长为5秒。此示例中的5秒时长为建议值,具体时长取决于关键帧。
channel_name = "your_channel_name"
playlist_name = "your_playlist_name.m3u8"
frag_count_config = 3
frag_duration_config = 5
create_result = bucket.create_live_channel(
        channel_name,
        oss2.models.LiveChannelInfo(
            status = 'enabled',
            description = 'your description here',
            target = oss2.models.LiveChannelInfoTarget(
                playlist_name = playlist_name,
                frag_count = frag_count_config,
                frag_duration = frag_duration_config)))

# 获取RTMP推流签名地址。
# 示例中的expires是一个相对时间,表示从现在开始此次推流过期的秒数。
# 获取签名后的signed_url后即可使用推流工具直接进行推流。一旦连接上OSS,即使超出设置的expires也不会断流,OSS仅在每次推流连接时检查expires是否合法。
signed_rtmp_url = bucket.sign_rtmp_url(channel_name, playlist_name, expires=3600)
print(signed_rtmp_url)

OSS访问私有Bucket中的文件时,需要在URL中加上签名。HLS的访问机制为动态访问m3u8索引文件,根据索引文件的内容多次请求下载最新的ts文件,此过程中的每一次请求都需要在URL中加上签名。

video2

为此,OSS对音视频数据的访问提供了动态签名机制,即只需在首次访问m3u8文件时在URL中添加x-oss-process=hls/sign, OSS将对返回的播放列表中的所有ts地址自动按照与m3u8完全相同的方式进行签名。

使用Python SDK动态签名机制访问音视频的示例如下:

# 获取观流的动态签名地址。
your_object_name = "test_rtmp_live/test.m3u8"
style = "hls/sign"
# 生成签名URL时,OSS默认会对Object完整路径中的正斜线(/)进行转义,从而导致生成的签名URL无法直接使用。
# 设置slash_safe为True,OSS不会对Object完整路径中的正斜线(/)进行转义,此时生成的签名URL可以直接使用。
signed_download_url = bucket.sign_url('GET', your_object_name, 3600, params={'x-oss-process': style}, slash_safe=True)
print(signed_download_url)