全部产品
Search
文档中心

对象存储 OSS:RTMP推流上传

更新时间:Dec 18, 2024

OSS支持使用RTMP协议推送H264编码的视频流和AAC编码的音频流到OSS。推送到OSS的音视频数据可用于点播或直播场景。本文介绍如何推送音视频流到OSS,以及如何播放推送到OSS的音视频数据。

使用限制

  • 只能使用RTMP推流的方式,不支持拉流。

  • 上传的音视频数据中必须包含视频流,且视频流格式为H264。

  • 上传的音视频数据中可选择是否包含音频流。若包含音频流,则只支持AAC格式的音频流,其他格式的音频流会被丢弃。

  • 转储只支持HLS协议。

  • 一个LiveChannel同时只能有一个客户端向其推流。

向OSS推送音视频数据

  1. 获取推流地址。

    使用SDK调用PutLiveChannel接口创建一个LiveChannel,并获取对应的推流地址。

    • 如果Bucket的权限控制(ACL)为公共读写(public-read-write),可直接使用获取的推流地址进行推流。

    • 如果Bucket ACL为公共读(public-read)或者私有(private),则需要进行签名操作。关于签名的具体步骤,请参见签名版本1

    仅Java SDK、Python SDK支持获取推流地址。

    Java

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.*;
    import java.util.List;
    import com.aliyun.oss.common.auth.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 填写Bucket名称,例如examplebucket。
            String bucketName = "examplebucket";
            // 填写LiveChannel名称。
            String liveChannelName = "yourLiveChannelName";
            // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
            String region = "cn-hangzhou";
    
            // 创建OSSClient实例。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
            OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)               
            .build();
    
            try {
                CreateLiveChannelRequest request = new CreateLiveChannelRequest(bucketName,
                        liveChannelName, "desc", LiveChannelStatus.Enabled, new LiveChannelTarget());
                CreateLiveChannelResult result = ossClient.createLiveChannel(request);
    
                // 获取推流地址。
                List<String> publishUrls = result.getPublishUrls();
                for (String item : publishUrls) {
                    // 获取不包含签名信息的推流地址。
                    System.out.println(item);
    
                    // 获取包含签名信息的推流地址。
                    LiveChannelInfo liveChannelInfo = ossClient.getLiveChannelInfo(bucketName, liveChannelName);
                    // expires表示过期时间,单位为Unix时间戳。本示例以设置过期时间为1小时为例。
                    long expires = System.currentTimeMillis() / 1000 + 3600;
                    // playlistName表示调用createLiveChannel接口时传入的具体名称。如果未传入该参数,则默认值为"playlist.m3u8"。您也可以通过调用getLiveChannelInfo接口获取该名称。
                    String signRtmpUrl = ossClient.generateRtmpUri(bucketName, liveChannelName, liveChannelInfo.getTarget().getPlaylistName(), expires);
                    System.out.println(signRtmpUrl);
                }
    
                // 获取播放地址。
                List<String> playUrls = result.getPlayUrls();
                for (String item : playUrls) {
                    System.out.println(item);
                }
            } catch (OSSException oe) {
                oe.printStackTrace();
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }

    返回的推流地址如下:

    rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel
    rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel?Expires=1688542428&OSSAccessKeyId=LTAI********&Signature=VfUgZt5N%2B6Uk4C9QH%2BzrRBTO2I****&playlistName=playlist.m3u8
    http://examplebucket.oss-cn-hangzhou.aliyuncs.com/test-channel/playlist.m3u8

    Python

    # -*- 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。
    # 填写存储空间名称,例如examplebucket。
    bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
    # 填写LiveChannel名称,例如test-channel。
    channel_name = "test-channel"
    channel_cfg = oss2.models.LiveChannelInfo(target = oss2.models.LiveChannelInfoTarget())
    channel = bucket.create_live_channel(channel_name, channel_cfg)
    publish_url = channel.publish_url
    # 生成RTMP推流的签名URL,并设置过期时间为3600秒。
    signed_publish_url = bucket.sign_rtmp_url(channel_name, "playlist.m3u8", 3600)
    # 打印未签名推流地址。
    print('publish_url='+publish_url)
    # 打印签名推流地址。
    print('signed_publish_url='+signed_publish_url)

    返回的推流地址如下:

    publish_url=rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel
    signed_publish_url=rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel?playlistName=playlist.m3u8&OSSAccessKeyId=LTAI********&Expires=1688543369&Signature=eqK8z0ZTSwznP7fkELy0ckt0Iv****
  2. 使用推流地址向OSS推送音视频数据。

    使用ffmpeg进行推流

    使用ffmpeg推送本地的视频文件到OSS,示例如下:

    ffmpeg -i 1.flv -c copy -f flv "rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live/test-channel?playlistName=playlist.m3u8&OSSAccessKeyId=LTAI********&Expires=1688543369&Signature=eqK8z0ZTSwznP7fkELy0ckt0Iv***"

    使用OBS进行推流

    1. 安装OBS Studio

    2. 在顶部导航栏,选择文件 > 设置

    3. 在左侧导航栏,单击推流

    4. 在弹出的对话框,按以下说明配置各项参数。

      参数

      说明

      服务

      下拉选择自定义

      服务器

      填写步骤1获取的不包含签名推流信息的地址:rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live

      串流密钥

      填写步骤1获取的签名推流信息:test-channel?playlistName=playlist.m3u8&OSSAccessKeyId=LTAI**************&Expires=1688543369&Signature=eqK8z0ZTSwznP7fkELy0ck********

    5. 单击确定

播放推送到OSS的音视频数据

直播场景

在推流的过程中,可以通过HLS协议播放正在推送的内容。各平台的播放方法如下:

  • 在Android、iOS等移动平台,直接在浏览器输入LiveChannel对应的播放地址即可。

  • Mac OS可以使用safari浏览器进行播放。

  • PC端可以安装VLC多媒体播放器进行播放。安装完成后,在VLC media player页面,选择媒体(M) > 打开网络串流(N),然后将获取的播放地址play_url填写至请输入网络URL文本框。

为了直播流畅,可以设置较小的FragDuration,例如2s。另外,GOP的大小建议与LiveChannel的FragDuration配置保持一致。OBS的GOP (即keyframe Interval)设置方法如下:

点播场景

推流过程中,OSS总是以直播流的方式推送或更新M3U8。您需要在推流结束后,调用PostVodPlaylist接口组装一个点播用的m3u8文件,然后使用该文件地址来播放。

对于点播的场景,可以设置较大的GOP来减少ts文件数,从而降低码率。

相关文档