You can ingest H.264-encoded video streams and Advanced Audio Coding (AAC)-encoded audio streams to Object Storage Service (OSS) over Real-Time Messaging Protocol (RTMP). Audio and video data uploaded to OSS can be used for video-on-demand (VOD) or live streaming. This topic describes how to ingest audio and video streams to OSS and play the uploaded audio and video data.
Limits
If you use RTMP, you can only ingest video or audio streams. You cannot pull the streams.
The uploaded audio and video data must include H.264 video streams.
You can specify whether to include audio streams in the audio and video data. Only AAC-encoded audio streams are supported for audio. Audio streams in other formats are discarded.
You can use only HTTP Live Streaming (HLS) to store audio and video data in OSS.
A LiveChannel can receive streams ingested only from one client at a time.
Ingest audio and video streams to OSS
Obtain ingest URLs.
Use an OSS SDK to call the PutLiveChannel operation to create a LiveChannel and obtain ingest URLs.
If you set the bucket access control list (ACL) to public-read-write, you can use the obtained ingest URLs to ingest audio and video streams to OSS.
If you set the bucket ACL to public-read or private, you must add signatures to the ingest URLs. For more information, see Add signatures to URLs.
You can use only OSS SDK for Java and OSS SDK for Python to obtain ingest URLs.
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"; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the name of the LiveChannel. String liveChannelName = "yourLiveChannelName"; // Create an OSSClient instance. OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { CreateLiveChannelRequest request = new CreateLiveChannelRequest(bucketName, liveChannelName, "desc", LiveChannelStatus.Enabled, new LiveChannelTarget()); CreateLiveChannelResult result = ossClient.createLiveChannel(request); // Query the ingest URL. List<String> publishUrls = result.getPublishUrls(); for (String item : publishUrls) { // Query the ingest URL that does not contain the signature information. System.out.println(item); // Query the ingest URL that contains the signature information. LiveChannelInfo liveChannelInfo = ossClient.getLiveChannelInfo(bucketName, liveChannelName); // expires specifies the validity period of the URL. The value of expires is a timestamp that follows the UNIX time format. In this example, the validity period is 1 hour. long expires = System.currentTimeMillis() / 1000 + 3600; // playlistName specifies the name of the playlist when you call the createLiveChannel operation. If you do not specify this parameter when you call the createLiveChannel operation, the default value "playlist.m3u8" is used. You can call the getLiveChannelInfo operation to query the name of the playlist. String signRtmpUrl = ossClient.generateRtmpUri(bucketName, liveChannelName, liveChannelInfo.getTarget().getPlaylistName(), expires); System.out.println(signRtmpUrl); } // Query the streaming URL. 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(); } } } }
Returned ingest URLs:
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 # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider()) # Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. # Specify the name of the bucket. Example: examplebucket. bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket') # Specify the name of the LiveChannel. Example: 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 # Generate a signed ingest URL based on RTMP and set the validity period of the URL to 3600. Unit: seconds. signed_publish_url = bucket.sign_rtmp_url(channel_name, "playlist.m3u8", 3600) # Display the unsigned ingest URL. print('publish_url='+publish_url) # Display the signed ingest URL. print('signed_publish_url='+signed_publish_url)
Returned ingest URLs:
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****
Use ingest URLs to ingest audio and video data to OSS.
Use FFmpeg to ingest audio and video streams
You can use FFmpeg to ingest local video files to OSS by running the following command:
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***"
Use OBS for stream ingest
Install Open Broadcaster Software (OBS).
In the top navigation bar, choose
.In the left-side navigation pane, click Stream.
In the dialog box that appears, configure the parameters described in the following table.
Parameter
Description
Stream Type
Select Custom Streaming Server from the drop-down list.
URL
Enter the unsigned ingest URL that is obtained in Step 1:
rtmp://examplebucket.oss-cn-hangzhou.aliyuncs.com/live
.Stream key
Enter the signed ingest URL that is obtained in Step 1:
test-channel?playlistName=playlist.m3u8&OSSAccessKeyId=LTAI*************&Expires=1688543369&Signature=eqK8z0ZTSwznP7fkELy0ck********
.Click OK.
Play the audio and video data uploaded to OSS
Live streaming
During stream ingest, you can use HLS to play the audio and video data that is being uploaded on the following platforms:
On mobile platforms such as Android and iOS, enter the streaming URL of a LiveChannel in the browser.
On a macOS platform, use Safari to play the audio and video data.
On a computer, install the VLC media player to play the audio and video data. After you install the VLC media player, choose
on the VLC media player page, and then enter the obtained playback URL in the Please enter network URL field.
To ensure a smooth streaming experience, you can set FragDuration to a small value, such as 2s. In addition, we recommend that you set the Group of Pictures (GOP) to a fixed value that is the same as that of FragDuration of the LiveChannel. The following figure shows how to configure GOP (Keyframe Interval) in OBS.
VOD
When you ingest a stream to OSS, OSS uses live streaming to ingest or update M3U8 objects. You must call the PostVodPlaylist operation after stream ingest to assemble an M3U8 object for VOD and use the object URL to play the uploaded audio and video data.
In VOD scenarios, you can also set a larger GOP to reduce the number of transport stream (TS) objects and the bitrate.