边转边播是面向视频在线播放需求的实时转码功能。通过阅读本文,您可以了解边转边播功能的优势以及如何使用边转边播。
功能简介
不同于媒体转码需要在视频上传完成后等待整个视频转码完成才能播放,边转边播作为实时转码功能,可以实现原视频文件上传完成后立即开始播放,并在播放时仅对需要播放的视频片段进行转码。边转边播主要能为您带来:
边播放边转码,播放无需等待。
转码优化,秒级开播跳播,接近本地的播放体验。
不播放不转码,即使转码文件删除了也能重新转,显著节省转码和存储成本。
支持几十种转码参数,转码参数可高度自定义。
兼容性高,支持300+种音视频格式。
边转边播不支持匿名播放。
使用流程
将视频文件上传到对象存储OSS。
通过GenerateVideoPlaylist接口快速生成媒体播放列表文件,并使用OSS的签名功能对播放列表进行签名,最终获取签名后的播放列表。
播放器获取播放列表进行播放,播放过程中自动触发边转边播功能。
使用场景
网盘:用户上传视频到网盘,各种网盘客户端立即能根据网络情况选择不同的分辨率进行播放。既保证了播放的实时性,又能确保视频在不同设备上的兼容性。且网盘中大部分视频都是冷视频,使用边转边播功能,没有被用户播放的视频内容不会触发转码,极大节省了转码和存储成本。
聊天软件视频预览:在即时通讯或社交媒体平台中,发送方把视频发送完毕(服务端接收完成),接收方立刻可以开始播放视频,提高交流的实时性。历史聊天记录中长期不被观看的视频,转码生成的视频文件可以定期清理以降低存储成本,再次播放时亦可立刻播放。
网络论坛与博客交流:使用边转边播功能,用户在要分享的原视频上传完成后,其他用户可以立即播放转码后的视频,同时保证视频播放的流畅性、清晰度和兼容性。
功能特性
边转边播的更多功能特性如下表所示。
特性 | 说明 |
标准化 |
|
低成本 |
|
高效率 |
|
支持音视频格式列表
边转边播支持的音视频格式有300多种,几乎包含了所有常见的音视频格式。下面是边转边播支持的部分常见音视频格式。
输入视频格式 | avi、mov、flv、mkv、webm、mpeg、wmv、rm、vob、ts等 |
输入音频格式 | mp3、wav、aac、flac、wma等 |
输出容器格式 | ts |
前提条件
已创建并获取AccessKey。具体操作,请参见创建AccessKey。
已开通OSS服务、创建存储空间并上传文件到存储空间。具体操作,请参见控制台快速入门。
您也可以调用API接口创建项目。具体操作,请参见CreateProject - 创建项目。
您可以调用ListProjects - 列出所有项目信息的列表接口列出指定地域下已创建的所有项目信息。
使用边转边播功能时,您需要为RAM用户授予IMM处理所需的相关权限。具体操作,请参见权限。
边转边播需要使用到OSS的媒体处理能力(x-oss-process处理方式)。请在OSS配额中心申请“开启新版本IMM数据处理能力”。
使用边转边播前,需要先绑定IMM Project。关于控制台和API如何绑定,请参见快速入门和AttachOSSBucket - 绑定对象存储桶。
如您对源视频或输出目标视频所在Bucket启用了防盗链,请确保您设置“允许空Referer”的防盗链策略。防盗链参见Referer防盗链。
如您的播放器需跨域访问OSS,请务必为目标视频所在的Bucket启用OSS跨域访问,请参见:跨域设置。
使用方法
使用Media Playlist示例
转码信息
源视频信息
视频格式:AVI
视频源地址:oss://your-oss-bucket-name/test.avi
目标视频信息
转码分片大小:10秒
预转视频长度:36秒
视频流格式:H.264
视频分辨率:1280x720
视频帧率:25 fps
视频码率:2 Mbps
音频流格式:AAC
音频码率:128 Kbps
目标文件存储路径前缀:oss://your-oss-bucket-name/output/media
步骤一:生成播放列表
请求示例
{ "ProjectName": "test-project", "SourceURI": "oss://your-oss-bucket-name/test.avi", "Targets": [ { "Audio": { "TranscodeAudio": { "Codec": "aac", "Bitrate": 128000, "SampleRate": 44100 } }, "Duration": 10, "InitialSegments": [ 2, 2, 2 ], "InitialTranscode": 36, "URI": "oss://your-oss-bucket-name/output/media", "Video": { "TranscodeVideo": { "Codec": "h264", "Bitrate": 2400000, "FrameRate": 25, "Resolution": "1280x", "ScaleType": "fit" } } } ] }
返回示例
{ "RequestId": "********-3ADC-576A-BD1E-************", "VideoPlaylist": [ { "FrameRate": "25", "Resolution": "1280x720", "Token": "3d8ca7d6b3**********4b3cb69fe3bf", "URI": "oss://your-oss-bucket-name/output/media.m3u8" } ] }
示例代码
# -*- coding: utf-8 -*- import json from alibabacloud_imm20200930 import models as imm_20200930_models from alibabacloud_imm20200930.client import Client as imm20200930Client from alibabacloud_tea_openapi import models as open_api_models class Sample: def __init__(self): pass @staticmethod def create_client( access_key_id: str, access_key_secret: str, ) -> imm20200930Client: """ 使用AccessKey ID和AccessKey Secret初始化账号Client。 @param access_key_id: @param access_key_secret: @return: Client @throws Exception """ config = open_api_models.Config( # 填写您的AccessKey ID。 access_key_id=access_key_id, # 填写您的AccessKey Secret。 access_key_secret=access_key_secret ) # 填写访问的IMM域名。 config.endpoint = f'imm.cn-hangzhou.aliyuncs.com' return imm20200930Client(config) @staticmethod def main() -> None: # 填写IMM的AccessKey ID、AccessKey Secret,建议从配置中读取。 imm_access_key_id = "yourAccessKeyId" imm_access_key_secret = "yourAccessKeySecret" # 填写项目名称。 project_name = "test-project" # 填写源视频的OSS URI。 source_uri = "oss://your-oss-bucket-name/test.avi" # 目标URI。 target_uri = "oss://your-oss-bucket-name/output/media" # 初始化客户端。 client = Sample.create_client(imm_access_key_id, imm_access_key_secret) # 创建Target。 target = imm_20200930_models.GenerateVideoPlaylistRequestTargets( audio=imm_20200930_models.TargetAudio( transcode_audio=imm_20200930_models.TargetAudioTranscodeAudio( codec="aac", bitrate=128000, sample_rate=44100, ) ), duration=10, initial_segments=[2, 2, 2], initial_transcode=36, uri=target_uri, video=imm_20200930_models.TargetVideo( transcode_video=imm_20200930_models.TargetVideoTranscodeVideo( codec="h264", bitrate=2400000, frame_rate=25, resolution="1280x", scale_type="fit", ) ), ) # 创建API请求。 req = imm_20200930_models.GenerateVideoPlaylistRequest( project_name=project_name, source_uri=source_uri, targets=[target] ) # 打印API的请求值。 print(json.dumps(req.to_map(), indent=4)) # 发起请求 response = client.generate_video_playlist(req) # 打印API的返回值。 print(json.dumps(response.body.to_map(), indent=4)) if __name__ == '__main__': Sample.main()
package main import ( "fmt" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" imm "github.com/alibabacloud-go/imm-20200930/v2/client" "github.com/alibabacloud-go/tea/tea" ) func main() { // 初始化IMM客户端。 immClient, err := imm.NewClient(&openapi.Config{ RegionId: tea.String("cn-hangzhou"), // 填写项目所在地域ID。 AccessKeyId: tea.String("your_access_key_id"), // 填写RAM用户的AccessKey ID。 AccessKeySecret: tea.String("your_access_key_secret"), // 填写RAM用户的AccessKey Secret。 }) if err != nil { // 错误处理。 panic(err) } // 填写项目名称。 projectName := "test-project" // 填写视频的OSS URI。 sourceUri := "oss://your-oss-bucket-name/test.avi" // 目标URI。 targetUri := "oss://your-oss-bucket-name/output/media" target := &imm.GenerateVideoPlaylistRequestTargets{ Audio: &imm.TargetAudio{ TranscodeAudio: &imm.TargetAudioTranscodeAudio{ Bitrate: tea.Int32(98304), Codec: tea.String("aac"), SampleRate: tea.Int32(44100), }, }, Duration: tea.Float32(10), InitialSegments: []*float32{tea.Float32(2), tea.Float32(2), tea.Float32(2)}, InitialTranscode: tea.Float32(36), URI: tea.String(targetUri), Video: &imm.TargetVideo{ TranscodeVideo: &imm.TargetVideoTranscodeVideo{ Codec: tea.String("h264"), Bitrate: tea.Int32(2400000), FrameRate: tea.Float32(25), Resolution: tea.String("1280x"), ScaleType: tea.String("fit"), }, }, } // 创建API请求。 req := &imm.GenerateVideoPlaylistRequest{ ProjectName: tea.String(projectName), SourceURI: tea.String(sourceUri), Targets: []*imm.GenerateVideoPlaylistRequestTargets{target}, } // 发起请求 res, err := immClient.GenerateVideoPlaylist(req) if err != nil { panic(err) } // 打印API的返回值。 fmt.Println("Response:", *res.Body) }
// This file is auto-generated, don't edit it. Thanks. package com.aliyun.sample; import com.aliyun.tea.*; public class Sample { /** * <b>description</b> : * <p>使用AK&SK初始化账号Client</p> * @return Client * * @throws Exception */ public static com.aliyun.teaopenapi.Client createClient() throws Exception { // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。 // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。 com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")) // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")); // Endpoint 请参考 https://api.aliyun.com/product/imm config.endpoint = "imm.cn-beijing.aliyuncs.com"; return new com.aliyun.teaopenapi.Client(config); } /** * <b>description</b> : * <p>API 相关</p> * * @param path string Path parameters * @return OpenApi.Params */ public static com.aliyun.teaopenapi.models.Params createApiInfo() throws Exception { com.aliyun.teaopenapi.models.Params params = new com.aliyun.teaopenapi.models.Params() // 接口名称 .setAction("GenerateVideoPlaylist") // 接口版本 .setVersion("2020-09-30") // 接口协议 .setProtocol("HTTPS") // 接口 HTTP 方法 .setMethod("POST") .setAuthType("AK") .setStyle("RPC") // 接口 PATH .setPathname("/") // 接口请求体内容格式 .setReqBodyType("json") // 接口响应体内容格式 .setBodyType("json"); return params; } public static void main(String[] args_) throws Exception { java.util.List<String> args = java.util.Arrays.asList(args_); com.aliyun.teaopenapi.Client client = Sample.createClient(); com.aliyun.teaopenapi.models.Params params = Sample.createApiInfo(); // query params java.util.Map<String, Object> queries = new java.util.HashMap<>(); queries.put("ProjectName", "test-project"); queries.put("SourceURI", "oss://your-oss-bucket-name/test.avi"); queries.put("Targets", "[{\"Video\":{\"TranscodeVideo\":{\"Codec\":\"h264\",\"Bitrate\":128000,\"FrameRate\":25,\"Resolution\":\"1280x\"}},\"Audio\":{\"TranscodeAudio\":{\"SampleRate\":44100,\"Codec\":\"aac\",\"Bitrate\":2400000}},\"Duration\":10,\"InitialSegments\":[2,2,2],\"InitialTranscode\":36,\"URI\":\"oss://your-oss-bucket-name/output/media\"}]"); // runtime options com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions(); com.aliyun.teaopenapi.models.OpenApiRequest request = new com.aliyun.teaopenapi.models.OpenApiRequest() .setQuery(com.aliyun.openapiutil.Client.query(queries)); // 复制代码运行请自行打印 API 的返回值 // 返回值实际为 Map 类型,可从 Map 中获得三类数据:响应体 body、响应头 headers、HTTP 返回的状态码 statusCode。 client.callApi(params, request, runtime); } }
步骤二:对播放列表签名
# -*- coding: utf-8 -*-
import os
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 从环境变量中获取访问凭证。运行本代码示例之前,请先配置环境变量。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。请按实际情况填写。
endpoint = 'yourEndpoint'
# 填写Endpoint对应的Region信息,例如cn-hangzhou。
region = 'cn-hangzhou'
# 目标Bucket名称。
bucket_name = 'your-oss-bucket-name'
# 填写生成的播放列表名称。
key = 'output/media.m3u8'
# 指定Bucket实例,所有文件相关的方法都需要通过Bucket实例来调用。
bucket = oss2.Bucket(auth, endpoint, bucket_name, region=region)
# x-oss-process的处理方式为hls/sign,live_1。
params = {}
params.update({oss2.Bucket.PROCESS: 'hls/sign,live_1'})
# 签名URL。
url = bucket.sign_url('GET', key, 7200, params=params, slash_safe=True)
# 生成的URL可以直接在HLS播放器中播放。
print(url)
# 本例生成的URL: http://your-oss-bucket-name.yourendpoint/output/media.m3u8?x-oss-process=hls%2Fsign%2Clive_1&x-oss-signature-version=OSS2&x-oss-expires=1683619052&x-oss-access-key-id=yourAccessKeyId&x-oss-signature=4Lja6Sgb7zXWzY9R9QTRe4FxI240fApDavp%2BSMj3ufg%3D
package main
import (
"fmt"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"net/http"
"net/url"
"os"
"strings"
)
func main() {
// 从环境变量中获取访问凭证。运行本代码示例之前,请先配置环境变量。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 创建OSSClient实例。
// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
// yourRegion填写Endpoint对应的Region信息,例如cn-hangzhou。
client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider), oss.AuthVersion(oss.AuthV4), oss.Region("yourRegion"))
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 填写Bucket名称,例如your-oss-bucket-name。
bucket, err := client.Bucket("your-oss-bucket-name")
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 使用oss hls/sign签名。"hls/sign,live_1" 是指使用边转边播的能力,为固定的格式。
// 填写m3u8的完整路径,例如output/media.m3u8。
// 填写签名的有效时间,例如7200,两个小时有效。
signedURL, err := bucket.SignURL("output/media.m3u8", http.MethodGet, 7200, oss.Process("hls/sign,live_1"))
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 转换为可供播放器使用的URL。
rawUrl, err := url.Parse(signedURL)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
rawUrl.RawPath = strings.Replace(rawUrl.RawPath, "%2F", "/", -1)
// 打印输出签名后的URL。
fmt.Println(rawUrl.String())
// 签名输出URL可以直接粘贴到HLS播放器中播放。
//http://your-oss-bucket-name.yourEndpoint/output/media.m3u8?x-oss-access-key-id=yourAccessKeyId&x-oss-expires=1683618084&x-oss-process=hls%2Fsign%2Clive_1&x-oss-signature=%2BqTZ0R04Ft065gdyoP6f9yJdd1UXi%2F8eoxd9c9Stl2g%3D&x-oss-signature-version=OSS2
}
package com.aliyun.sample;
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import java.net.URL;
import java.util.Date;
public class demo {
public static void main(String[] args) throws Throwable {
// 以华东2(北京)的外网Endpoint为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
String region = "cn-beijing";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "test-project";
// 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectKey = "output/media.m3u8";
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
// 设置URL过期时间
Date expiration = new Date(new Date().getTime() + 7200 * 1000); // 2小时
GeneratePresignedUrlRequest request=new GeneratePresignedUrlRequest(bucketName, objectKey, HttpMethod.GET);
request.setExpiration(expiration);
request.setProcess("hls/sign,live_1");
// 生成签名URL
URL signedUrl = ossClient.generatePresignedUrl(request);
// 输出签名URL
System.out.println(signedUrl);
// 关闭OSS客户端
// 关闭OSSClient。
ossClient.shutdown();
try {
// 设置签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
URL url = ossClient.generatePresignedUrl(bucketName, objectKey, expiration);
System.out.println(url);
} catch (OSSException oe) {
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();
}
}
}
}
步骤三:播放视频
步骤二:对播放列表签名中生成的签名后的URL,可以直接粘贴到HLS播放器中播放,操作方法如下。
Mac使用Safari播放
Mac系统的Safari播放器支持HLS视频播放,您可以直接粘贴URL到Safari地址栏播放。
使用Aliplayer播放
打开阿里云Aliplayer播放器,粘贴URL到地址栏后播放,如下图所示。
说明您也可以集成阿里云播放器SDK到您的业务系统中,在您的业务系统中播放。具体操作,请参见Web播放器简介。
使用HLS播放器播放
把签名后的URL粘贴到HLS播放器中。
使用Master Playlist示例
转码信息
源视频信息
视频格式:AVI
视频源地址:oss://your-oss-bucket-name/test.avi
Master playlist地址:oss://your-oss-bucket-name/output/master.m3u8
目标视频信息1
转码分片大小:10秒
预转视频长度:36秒
视频流格式:H.264
视频分辨率:1920x1080
视频帧率:25 fps
音频流格式:AAC
音频码率:128 Kbps
目标文件存储路径前缀:oss://your-oss-bucket-name/output/1080p/1080p
目标视频信息2
转码分片大小:10秒
预转视频长度:36秒
视频流格式:H.264
视频分辨率:1280x720
视频帧率:25 fps
音频流格式:AAC
音频码率:96 Kbps
目标文件存储路径前缀:oss://your-oss-bucket-name/output/720p/720p
目标视频信息3
转码分片大小:10秒
预转视频长度:36秒
视频流格式:H.264
视频分辨率:720x540
视频帧率:25 fps
音频流格式:AAC
音频码率:64 Kbps
目标文件存储路径前缀:oss://your-oss-bucket-name/output/540p/540p
步骤一:生成播放列表
请求示例
{ "MasterURI": "oss://your-oss-bucket-name/output/master.m3u8", "ProjectName": "test-project", "SourceSubtitles": [], "SourceURI": "oss://your-oss-bucket-name/test.avi", "Targets": [ { "Audio": { "TranscodeAudio": { "Bitrate": 131072, "Codec": "aac", "SampleRate": 44100 } }, "Duration": 10, "InitialSegments": [ 2, 2, 2 ], "InitialTranscode": 36, "URI": "oss://your-oss-bucket-name/output/1080p/1080p", "Video": { "TranscodeVideo": { "CRF": 26, "Codec": "h264", "FrameRate": 25, "Resolution": "1920x", "ScaleType": "fit" } } }, { "Audio": { "TranscodeAudio": { "Bitrate": 98304, "Codec": "aac", "SampleRate": 44100 } }, "Duration": 10, "InitialSegments": [ 2, 2, 2 ], "InitialTranscode": 36, "URI": "oss://your-oss-bucket-name/output/720p/720p", "Video": { "TranscodeVideo": { "CRF": 26, "Codec": "h264", "FrameRate": 25, "Resolution": "1280x", "ScaleType": "fit" } } }, { "Audio": { "TranscodeAudio": { "Bitrate": 65536, "Codec": "aac", "SampleRate": 44100 } }, "Duration": 10, "InitialSegments": [ 2, 2, 2 ], "InitialTranscode": 36, "URI": "oss://your-oss-bucket-name/output/540p/540p", "Video": { "TranscodeVideo": { "CRF": 26, "Codec": "h264", "FrameRate": 25, "Resolution": "720x", "ScaleType": "fit" } } } ] }
返回示例
{ "Duration": 60.085, "MasterURI": "oss://your-oss-bucket-name/output/master.m3u8", "RequestId": "********-3ADC-576A-BD1E-************", "Token": "1deb790e****************231a6f9d", "VideoPlaylist": [ { "FrameRate": "25", "Resolution": "720x406", "Token": "8bcd9bc0****************67a65f48", "URI": "oss://your-oss-bucket-name/output/540p/540p.m3u8" }, { "FrameRate": "25", "Resolution": "1280x720", "Token": "89ca4337****************cd031957", "URI": "oss://your-oss-bucket-name/output/720p/720p.m3u8" }, { "FrameRate": "25", "Resolution": "1920x1080", "Token": "11fb1afb****************4f3683fc", "URI": "oss://your-oss-bucket-name/output/1080p/1080p.m3u8" } ] }
示例代码
# -*- coding: utf-8 -*- import json from alibabacloud_imm20200930 import models as imm_20200930_models from alibabacloud_imm20200930.client import Client as imm20200930Client from alibabacloud_tea_openapi import models as open_api_models class Sample: def __init__(self): pass @staticmethod def create_client( access_key_id: str, access_key_secret: str, ) -> imm20200930Client: """ 使用AccessKey ID和AccessKey Secret初始化账号Client。 @param access_key_id: @param access_key_secret: @return: Client @throws Exception """ config = open_api_models.Config( # 填写您的AccessKey ID。 access_key_id=access_key_id, # 填写您的AccessKey Secret。 access_key_secret=access_key_secret ) # 填写访问的IMM域名。 config.endpoint = f'imm.cn-hangzhou.aliyuncs.com' return imm20200930Client(config) @staticmethod def main() -> None: # 填写IMM的AccessKey ID、AccessKey Secret,建议从配置中读取。 imm_access_key_id = "yourAccessKeyId" imm_access_key_secret = "yourAccessKeySecret" # 填写项目名称。 project_name = "test-project" # 填写源视频的OSS URI。 source_uri = "oss://your-oss-bucket-name/test.avi" # 目标URI。 target_uri_prefix = "oss://your-oss-bucket-name/output" master_uri = f"{target_uri_prefix}/master.m3u8" target_1080p_uri = f"{target_uri_prefix}/1080p/1080p" target_720p_uri = f"{target_uri_prefix}/720p/720p" target_540p_uri = f"{target_uri_prefix}/540p/540p" # 初始化客户端。 client = Sample.create_client(imm_access_key_id, imm_access_key_secret) # 创建 1080p Target。 target_1080p = imm_20200930_models.GenerateVideoPlaylistRequestTargets( audio=imm_20200930_models.TargetAudio( transcode_audio=imm_20200930_models.TargetAudioTranscodeAudio( codec="aac", bitrate=131072, sample_rate=44100, ) ), duration=10, initial_segments=[2, 2, 2], initial_transcode=36, uri=target_1080p_uri, video=imm_20200930_models.TargetVideo( transcode_video=imm_20200930_models.TargetVideoTranscodeVideo( codec="h264", crf=26, frame_rate=25, resolution="1920x", scale_type="fit", ) ), ) # 创建 720p Target。 target_720p = imm_20200930_models.GenerateVideoPlaylistRequestTargets( audio=imm_20200930_models.TargetAudio( transcode_audio=imm_20200930_models.TargetAudioTranscodeAudio( codec="aac", bitrate=98304, sample_rate=44100, ) ), duration=10, initial_segments=[2, 2, 2], initial_transcode=36, uri=target_720p_uri, video=imm_20200930_models.TargetVideo( transcode_video=imm_20200930_models.TargetVideoTranscodeVideo( codec="h264", crf=26, frame_rate=25, resolution="1280x", scale_type="fit", ) ), ) # 创建 540p Target。 target_540p = imm_20200930_models.GenerateVideoPlaylistRequestTargets( audio=imm_20200930_models.TargetAudio( transcode_audio=imm_20200930_models.TargetAudioTranscodeAudio( codec="aac", bitrate=65536, sample_rate=44100, ) ), duration=10, initial_segments=[2, 2, 2], initial_transcode=36, uri=target_540p_uri, video=imm_20200930_models.TargetVideo( transcode_video=imm_20200930_models.TargetVideoTranscodeVideo( codec="h264", crf=26, frame_rate=25, resolution="720x", scale_type="fit", ) ), ) # 创建API请求。 req = imm_20200930_models.GenerateVideoPlaylistRequest( project_name=project_name, source_uri=source_uri, master_uri=master_uri, targets=[target_1080p, target_720p, target_540p] ) # 打印API的请求值。 print(json.dumps(req.to_map(), indent=4)) # 发起请求 response = client.generate_video_playlist(req) # 打印API的返回值。 print(json.dumps(response.body.to_map(), indent=4)) if __name__ == '__main__': Sample.main()
package main import ( "fmt" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" imm "github.com/alibabacloud-go/imm-20200930/v2/client" "github.com/alibabacloud-go/tea/tea" ) func main() { // 初始化IMM客户端。 immClient, err := imm.NewClient(&openapi.Config{ RegionId: tea.String("cn-hangzhou"), // 填写项目所在地域ID。 AccessKeyId: tea.String("your_access_key_id"), // 填写RAM用户的AccessKey ID。 AccessKeySecret: tea.String("your_access_key_secret"), // 填写RAM用户的AccessKey Secret。 }) if err != nil { // 错误处理。 panic(err) } // 填写项目名称。 projectName := "test-project" // 填写视频的OSS URI。 sourceUri := "oss://your-oss-bucket-name/test.avi" // 目标URI。 targetURIPrefix := "oss://your-oss-bucket-name/output" masterURI := targetURIPrefix + "/master.m3u8" target1080pURI := targetURIPrefix + "/1080p/1080p" target720pURI := targetURIPrefix + "/720p/720p" target540pURI := targetURIPrefix + "/540p/540p" target1080p := &imm.GenerateVideoPlaylistRequestTargets{ Audio: &imm.TargetAudio{ TranscodeAudio: &imm.TargetAudioTranscodeAudio{ Bitrate: tea.Int32(131072), Codec: tea.String("aac"), SampleRate: tea.Int32(44100), }, }, Duration: tea.Float32(10), InitialSegments: []*float32{tea.Float32(2), tea.Float32(2), tea.Float32(2)}, InitialTranscode: tea.Float32(36), URI: tea.String(target1080pURI), Video: &imm.TargetVideo{ TranscodeVideo: &imm.TargetVideoTranscodeVideo{ Codec: tea.String("h264"), CRF: tea.Float32(26), FrameRate: tea.Float32(25), Resolution: tea.String("1920x"), ScaleType: tea.String("fit"), }, }, } target720p := &imm.GenerateVideoPlaylistRequestTargets{ Audio: &imm.TargetAudio{ TranscodeAudio: &imm.TargetAudioTranscodeAudio{ Bitrate: tea.Int32(98304), Codec: tea.String("aac"), SampleRate: tea.Int32(44100), }, }, Duration: tea.Float32(10), InitialSegments: []*float32{tea.Float32(2), tea.Float32(2), tea.Float32(2)}, InitialTranscode: tea.Float32(36), URI: tea.String(target720pURI), Video: &imm.TargetVideo{ TranscodeVideo: &imm.TargetVideoTranscodeVideo{ Codec: tea.String("h264"), CRF: tea.Float32(26), FrameRate: tea.Float32(25), Resolution: tea.String("1280x"), ScaleType: tea.String("fit"), }, }, } target540p := &imm.GenerateVideoPlaylistRequestTargets{ Audio: &imm.TargetAudio{ TranscodeAudio: &imm.TargetAudioTranscodeAudio{ Bitrate: tea.Int32(65536), Codec: tea.String("aac"), SampleRate: tea.Int32(44100), }, }, Duration: tea.Float32(10), InitialSegments: []*float32{tea.Float32(2), tea.Float32(2), tea.Float32(2)}, InitialTranscode: tea.Float32(36), URI: tea.String(target540pURI), Video: &imm.TargetVideo{ TranscodeVideo: &imm.TargetVideoTranscodeVideo{ Codec: tea.String("h264"), CRF: tea.Float32(26), FrameRate: tea.Float32(25), Resolution: tea.String("720x"), ScaleType: tea.String("fit"), }, }, } // 创建API请求。 req := &imm.GenerateVideoPlaylistRequest{ ProjectName: tea.String(projectName), SourceURI: tea.String(sourceUri), MasterURI: tea.String(masterURI), Targets: []*imm.GenerateVideoPlaylistRequestTargets{target1080p, target720p, target540p}, } // 发起请求 res, err := immClient.GenerateVideoPlaylist(req) if err != nil { panic(err) } // 打印API的返回值。 fmt.Println("Response:", *res.Body) }
步骤二:对播放列表签名
您需要对返回的master playlist进行OSS URL签名。签名方式请参见步骤二:对播放列表签名。
步骤三:播放视频
播放方式请参见步骤三:播放视频。
常见问题
需要使用定制的播放器吗?
不需要。边转边播功能支持标准的HLS协议,您使用支持标准HLS协议的播放器(例如:阿里云Aliplayer播放器,Safari浏览器)即可使用边转边播功能。
输出文件包括有哪些?
我们会根据您指定的输入路径前缀生成m3u8文件和ts文件,m3u8文件立刻生成。
如果您指定了预转时长,系统将异步生成与该预转时长相对应的TS文件。未指定预转的部分将在视频播放时按需触发异步转码。如果视频从未播放,则不会为未指定预转的部分生成TS文件。例如,如果视频从15分钟的位置开始播放,系统仅会从该位置开始进行转码。相应生成的文件目录树如下:
.
├── outobjprefix.m3u8
├── outobjprefix-c280f054328fcde47c1732a8f2915009-0.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-1.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-2.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-3.ts
已经生成的ts文件手动删除后能正常播放吗?
可以。只要视频源文件和m3u8播放列表未被删除,手动删除部分或全部ts文件后,视频仍能正常播放。这是因为当m3u8播放列表再次被请求时,会触发ts文件的重新生成。这种方法允许对之前已播放但长时间未被观看的视频的ts文件进行清理,从而减少存储成本,而不影响视频未来的重新播放。
能使用非边转边播的m3u8文件做边转边播吗?
不允许使用非边转边播生成的m3u8文件来实现边转边播功能。
能使用CDN为边转边播加速吗?
可以。详情参见使用CDN为边转边播加速。