文档

边转边播

更新时间:

边转边播是面向视频在线播放需求的实时转码功能。通过阅读本文,您可以了解边转边播功能的优势以及如何使用边转边播。

功能简介

不同于媒体转码需要在视频上传完成后等待整个视频转码完成才能播放,边转边播作为实时转码功能,可以实现原视频文件上传完成后立即开始播放,并在播放时仅对需要播放的视频片段进行转码。边转边播主要能为您带来:

  • 边播放边转码,播放无需等待。

  • 转码优化,秒级开播跳播,接近本地的播放体验。

  • 不播放不转码,即使转码文件删除了也能重新转,显著节省转码和存储成本。

  • 支持几十种转码参数,转码参数可高度自定义。

  • 兼容性高,支持300+种音视频格式。

说明

边转边播不支持匿名播放。

使用流程

  1. 将视频文件上传到对象存储OSS。

  2. 通过GenerateVideoPlaylist接口快速生成媒体播放列表文件,并使用OSS的签名功能对播放列表进行签名,最终获取签名后的播放列表。

  3. 播放器获取播放列表进行播放,播放过程中自动触发边转边播功能。

image

使用场景

  • 网盘:用户上传视频到网盘,各种网盘客户端立即能根据网络情况选择不同的分辨率进行播放。既保证了播放的实时性,又能确保视频在不同设备上的兼容性。且网盘中大部分视频都是冷视频,使用边转边播功能,没有被用户播放的视频内容不会触发转码,极大节省了转码和存储成本。

  • 聊天软件视频预览:在即时通讯或社交媒体平台中,发送方把视频发送完毕(服务端接收完成),接收方立刻可以开始播放视频,提高交流的实时性。历史聊天记录中长期不被观看的视频,转码生成的视频文件可以定期清理以降低存储成本,再次播放时亦可立刻播放。

  • 网络论坛与博客交流:使用边转边播功能,用户在要分享的原视频上传完成后,其他用户可以立即播放转码后的视频,同时保证视频播放的流畅性、清晰度和兼容性。

功能特性

边转边播的更多功能特性如下表所示。

特性

说明

标准化

  • 支持标准HLS协议。

  • 支持Media playlist以及支持生成Master playlist。

  • 支持多视频流、多语音流、多字幕流播放。

  • 支持主流的HLS播放器。

  • 支持300+种主流的音视频格式。

低成本

  • 未播放的视频及切片将不进行转码,以降低转码成本。

  • 转码生成的视频切片可以被删除,以节省存储成本。在重新播放时,系统能够自动触发新的转码,从而确保在线播放体验不受影响。

高效率

  • 大规模集群支持实时转码。

  • 提供多种分辨率和码率的视频流,以适应不同的网络环境,确保播放的流畅性。

  • 无需等待转码完成,生成播放列表后即可播放。

  • 视频头分片大小自适应,片头加载更高效。

  • 智能预转。

支持音视频格式列表

边转边播支持的音视频格式有300多种,几乎包含了所有常见的音视频格式。下面是边转边播支持的部分常见音视频格式。

输入视频格式

avi、mov、flv、mkv、webm、mpeg、wmv、rm、vob、ts等

输入音频格式

mp3、wav、aac、flac、wma等

输出容器格式

ts

前提条件

  1. 已创建并获取AccessKey。具体操作,请参见创建AccessKey

  2. 已开通OSS服务、创建存储空间并上传文件到存储空间。具体操作,请参见控制台上传文件

  3. 已开通智能媒体管理服务并创建项目。具体操作,请参见开通产品创建项目

说明

您也可以调用API接口创建项目。具体操作,请参见CreateProject - 创建项目

您可以调用ListProjects - 列出所有项目信息的列表接口列出指定地域下已创建的所有项目信息。

  1. 使用边转边播功能时,您需要为RAM用户授予IMM处理所需的相关权限。具体操作,请参见权限

  2. 边转边播需要使用到OSS的媒体处理能力(x-oss-process处理方式)。请在OSS配额中心申请“开启新版本IMM数据处理能力”。

  3. 使用边转边播前,需要先绑定IMM Project。关于控制台和API如何绑定,请参见快速入门AttachOSSBucket

  4. 如您对源视频或输出目标视频所在Bucket启用了防盗链,请确保您设置“允许空Referer”的防盗链策略。防盗链参见Referer防盗链

  5. 如您的播放器需跨域访问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)
    }

步骤二:对播放列表签名

# -*- coding: utf-8 -*-
import os
import oss2

# 填写Bucket所在地域对应的Endpoint。请按实际情况填写。
endpoint = 'yourEndpoint'
# 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
# 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
# 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。如何配置环境变量,请参见https://help.aliyun.com/document_detail/2361894.html。
imm_access_key_id = os.getenv("AccessKeyId")
imm_access_key_secret = os.getenv("AccessKeySecret")
# 目标Bucket名称。
bucket_name = 'your-oss-bucket-name'
# 填写生成的播放列表名称。
key = 'output/media.m3u8'

# 指定Bucket实例,所有文件相关的方法都需要通过Bucket实例来调用。
# 必须使用oss2.AuthV2的签名方式。
bucket = oss2.Bucket(oss2.AuthV2(imm_access_key_id, imm_access_key_secret), endpoint, bucket_name)

# 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"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// 创建OSSClient实例。
	// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
	// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
	// 只支持Auth V2签名方式。
	client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret", oss.AuthVersion(oss.AuthV2))
	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

}

步骤三:播放视频

步骤二:对播放列表签名中生成的签名后的URL,可以直接粘贴到HLS播放器中播放,操作方法如下。

  • Mac使用Safari播放

    Mac系统的Safari播放器支持HLS视频播放,您可以直接粘贴URL到Safari地址栏播放。

  • 使用Aliplayer播放

    打开阿里云Aliplayer播放器,粘贴URL到地址栏后播放,如下图所示。

    说明

    您也可以集成阿里云播放器SDK到您的业务系统中,在您的业务系统中播放。具体操作,请参见Web播放器简介

    image..png

  • 使用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为边转边播加速