Transcode while streaming

更新时间:
复制 MD 格式

Transcode while streaming is a real-time transcoding feature for online video playback that starts playback immediately after upload and transcodes only the segments being watched.

Overview

Unlike ApsaraVideo Media Processing, which requires waiting for full video transcoding to complete after upload before playback can begin, transcode while streaming starts playback immediately after the source video finishes uploading. It only transcodes the video segments needed for playback. This approach delivers:

  • Transcoding during playback—no waiting required.

  • Optimized transcoding with sub-second startup and seek times—near-local playback experience.

  • No transcoding without playback. Even if transcoded files are deleted, they can be regenerated on demand—significantly reduced transcoding and storage costs.

  • Support for dozens of transcoding parameters—highly customizable settings.

  • High compatibility—supports over 300 audio and video formats.

Note

Transcode while streaming does not support anonymous playback.

Workflow

  1. Upload your video file to Object Storage Service (OSS).

  2. Use the GenerateVideoPlaylist API to quickly generate a media playlist file. Sign the playlist using OSS signing capabilities to obtain a signed playlist URL.

  3. The player fetches the signed playlist and begins playback. The transcode while streaming feature triggers automatically during playback.

Scenarios

  • Cloud storage: Users upload videos to cloud drives. Clients instantly select appropriate resolutions based on network conditions for playback. This ensures real-time playback and cross-device compatibility. Since most videos in cloud storage are rarely accessed ("cold"), transcode while streaming avoids transcoding unplayed content, greatly reducing transcoding and storage costs.

  • Chat app video previews: In instant messaging or social platforms, once the sender finishes uploading (and the server receives the file), the recipient can start playback immediately—enhancing real-time communication. Transcoded files for long-unviewed historical messages can be periodically cleaned up to lower storage costs, and playback remains instant upon re-access.

  • Online forums and blogs: After users upload source videos for sharing, others can immediately play transcoded versions—ensuring smooth playback, high definition, and broad format compatibility.

Features

The following table describes additional features.

Feature

Description

Standardization

  • Supports standard HTTP Live Streaming (HLS) protocol.

  • Supports media playlists and master playlist generation.

  • Supports multi-video stream, multi-audio stream, and multi-caption stream playback.

  • Compatible with mainstream HLS players.

  • Supports over 300 mainstream audio and video formats.

Low cost

  • Unplayed videos and segments are not transcoded, reducing transcoding costs.

  • Transcoded video segments can be deleted to save storage costs. Upon replay, the system automatically triggers new transcoding to maintain seamless playback.

High efficiency

  • Large-scale clusters support real-time transcoding.

  • Provides multiple video streams with varying resolutions and bitrates to adapt to different network conditions and ensure smooth playback.

  • Playback starts immediately after playlist generation—no need to wait for full transcoding.

  • Adaptive segment size for video headers enables faster initial loading.

  • Intelligent pre-transcoding.

Supported audio and video formats

Transcode while streaming supports over 300 audio and video formats. The following table lists some commonly supported formats.

Input video formats

avi, mov, flv, mkv, webm, mpeg, wmv, rm, vob, ts, and all other mainstream formats

Input audio formats

mp3, wav, aac, flac, wma, and all other mainstream formats

Output container format

ts

Prerequisites

  1. Create and obtain an AccessKey.

  2. Activate OSS, create a bucket, and upload files to it. For details, see Quick Start in console.

  3. Activate Intelligent Media Management (IMM) and create a project. For details, see Activate service and Create project.

    Note

    You can also call the CreateProject API to create a project.

    You can call the ListProjects API to list all projects in a specified region.

  4. Grant your Resource Access Management (RAM) user the required permissions for IMM operations.

  5. Before using transcode while streaming, bind an IMM project. For instructions on binding via console or API, see Quick Start and Bind OSS bucket.

  6. If hotlink protection is enabled on the bucket containing your source or output videos, ensure your hotlink protection policy allows empty Referer.

  7. If your player needs cross-domain access to OSS, enable OSS cross-origin resource sharing (CORS) for the target bucket. See CORS settings.

Usage

Media Playlist example

Transcoding configuration

  • Source video information

    • Format: AVI

    • Source URI: oss://your-oss-bucket-name/test.avi

  • Target video

    • Segment duration: 10 seconds

    • Pre-transcode duration: 36 seconds

    • Video codec: H.264

    • Resolution: 1280×720

    • Frame rate: 25 fps

    • Video bitrate: 2 Mbps

    • Audio codec: AAC

    • Audio bitrate: 128 Kbps

    • Output path prefix: oss://your-oss-bucket-name/output/media

Step 1: Generate playlist

Note

Refer to the Generate transcode while streaming playlist API documentation.

  • Request example

    {
      "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"
            }
          }
        }
      ]
    }
  • Response example

    {
      "RequestId": "********-3ADC-576A-BD1E-************",
      "VideoPlaylist": [
        {
          "FrameRate": "25",
          "Resolution": "1280x720",
          "Token": "3d8ca7d6b3**********4b3cb69fe3bf",
          "URI": "oss://your-oss-bucket-name/output/media.m3u8"
        }
      ]
    }
    
  • Sample code

    # -*- 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:
            """
            Initialize a client using AccessKey ID and AccessKey secret.
            @param access_key_id:
            @param access_key_secret:
            @return: Client
            @throws Exception
            """
            config = open_api_models.Config(
                # Your AccessKey ID.
                access_key_id=access_key_id,
                # Your AccessKey secret.
                access_key_secret=access_key_secret
            )
            # IMM endpoint.
            config.endpoint = f'imm.cn-hangzhou.aliyuncs.com'
            return imm20200930Client(config)
        @staticmethod
        def main() -> None:
            # Use IMM AccessKey ID and secret. Read from configuration if possible.
            imm_access_key_id = "yourAccessKeyId"
            imm_access_key_secret = "yourAccessKeySecret"
            # Project name.
            project_name = "test-project"
            # Source video OSS URI.
            source_uri = "oss://your-oss-bucket-name/test.avi"
            # Target URI.
            target_uri = "oss://your-oss-bucket-name/output/media"
            # Initialize client.
            client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
            # Create 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",
                    )
                ),
            )
            # Create API request.
            req = imm_20200930_models.GenerateVideoPlaylistRequest(
                project_name=project_name,
                source_uri=source_uri,
                targets=[target]
            )
            # Print request.
            print(json.dumps(req.to_map(), indent=4))
            # Send request.
            response = client.generate_video_playlist(req)
            # Print response.
            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() {
    	// Initialize IMM client.
    	immClient, err := imm.NewClient(&openapi.Config{
    		RegionId:        tea.String("cn-hangzhou"),            // Region ID of your project.
    		AccessKeyId:     tea.String("your_access_key_id"),     // RAM user AccessKey ID.
    		AccessKeySecret: tea.String("your_access_key_secret"), // RAM user AccessKey secret.
    	})
    	if err != nil {
    		// Handle error.
    		panic(err)
    	}
    	// Project name.
    	projectName := "test-project"
    	// Video OSS URI.
    	sourceUri := "oss://your-oss-bucket-name/test.avi"
    	// Target 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"),
    			},
    		},
    	}
    	// Create API request.
    	req := &imm.GenerateVideoPlaylistRequest{
    		ProjectName: tea.String(projectName),
    		SourceURI:   tea.String(sourceUri),
    		Targets:     []*imm.GenerateVideoPlaylistRequestTargets{target},
    	}
    	// Send request.
    	res, err := immClient.GenerateVideoPlaylist(req)
    	if err != nil {
    		panic(err)
    	}
    	// Print response.
    	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 {
        /**
         * description :
         * <p>Initialize client using AK&amp;SK</p>
         * @return Client
         * 
         * @throws Exception
         */
        public static com.aliyun.teaopenapi.Client createClient() throws Exception {
            // Leaking credentials may compromise all resources under your account. This example is for reference only.
            // Use STS for better security. See https://help.aliyun.com/document_detail/378657.html for more options.
            com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                    // Required. Ensure ALIBABA_CLOUD_ACCESS_KEY_ID is set as an environment variable.
                    .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                    // Required. Ensure ALIBABA_CLOUD_ACCESS_KEY_SECRET is set as an environment variable.
                    .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);
        }
        /**
         * description :
         * <p>API info</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()
                    // API name
                    .setAction("GenerateVideoPlaylist")
                    // API version
                    .setVersion("2020-09-30")
                    // Protocol
                    .setProtocol("HTTPS")
                    // HTTP method
                    .setMethod("POST")
                    .setAuthType("AK")
                    .setStyle("RPC")
                    // Path
                    .setPathname("/")
                    // Request body format
                    .setReqBodyType("json")
                    // Response body format
                    .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 parameters
            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));
            // Run and print API response.
            // Response is a Map containing body, headers, and statusCode.
            client.callApi(params, request, runtime);
        }
    }

Step 2: Sign the playlist

# -*- coding: utf-8 -*-
import os
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Get credentials from environment variables. Configure them before running.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Endpoint for your bucket's region.
endpoint = 'yourEndpoint'
# Region ID, e.g., cn-hangzhou.
region = 'cn-hangzhou'
# Bucket name.
bucket_name = 'your-oss-bucket-name'
# Playlist name.
key = 'output/media.m3u8'
# Create bucket instance.
bucket = oss2.Bucket(auth, endpoint, bucket_name, region=region) 
# Set x-oss-process to hls/sign,live_1.
params = {}
params.update({oss2.Bucket.PROCESS: 'hls/sign,live_1'})
# Generate signed URL.
url = bucket.sign_url('GET', key, 7200, params=params, slash_safe=True)
# Use this URL directly in an HLS player.
print(url)
# Example 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() {
	// Get credentials from environment variables. Configure them before running.
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// Create OSS client.
	// yourEndpoint: e.g., https://oss-cn-hangzhou.aliyuncs.com for China (Hangzhou).
	// yourRegion: e.g., 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 name.
	bucket, err := client.Bucket("your-oss-bucket-name")
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// Use oss hls/sign. "hls/sign,live_1" enables transcode while streaming.
	// Full path to m3u8, e.g., output/media.m3u8.
	// Signature validity: 7200 seconds (2 hours).
	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)
	}
	// Format for player use.
	rawUrl, err := url.Parse(signedURL)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	rawUrl.RawPath = strings.Replace(rawUrl.RawPath, "%2F", "/", -1)
	// Print signed URL.
	fmt.Println(rawUrl.String())
	// Paste this URL into an HLS player.
	//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 {
        // Endpoint example: https://oss-cn-beijing.aliyuncs.com. Adjust for your region.
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String region = "cn-beijing";
        // Get credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // Required. Ensure ALIBABA_CLOUD_ACCESS_KEY_ID is set.
                .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                // Required. Ensure ALIBABA_CLOUD_ACCESS_KEY_SECRET is set.
                .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Bucket name.
        String bucketName = "test-project";
        // Object path (exclude bucket name).
        String objectKey = "output/media.m3u8";
        // Create OSS client.
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
        // Set URL expiration (2 hours).
        Date expiration = new Date(new Date().getTime() + 7200 * 1000);
        GeneratePresignedUrlRequest request=new GeneratePresignedUrlRequest(bucketName, objectKey, HttpMethod.GET);
        request.setExpiration(expiration);
        request.setProcess("hls/sign,live_1");
        // Generate signed URL.
        URL signedUrl = ossClient.generatePresignedUrl(request);
        // Print URL.
        System.out.println(signedUrl);
        // Close OSS client.
        ossClient.shutdown();         
        try {
            // Example: 1-hour expiration.
            URL url = ossClient.generatePresignedUrl(bucketName, objectKey, expiration);
            System.out.println(url);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException. Request reached OSS but was rejected.");
            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 a ClientException. Client encountered a serious internal issue.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

Step 3: Play the video

Paste the signed URL from Step 2: Sign the playlist directly into an HLS player.

  • Play in Safari on Mac

    Safari on macOS supports HLS playback. Paste the URL into the address bar.

  • Play with Aliplayer

    Open the Alibaba Cloud Aliplayer and paste the URL into the address bar.

    Note

    You can also integrate the ApsaraVideo Player SDK into your application. See Web player overview.

  • Play with an HLS player

    Paste the signed URL into any HLS-compatible player.

Master Playlist example

Transcoding configuration

  • Source video

    • Format: AVI

    • Source URI: oss://your-oss-bucket-name/test.avi

  • Master playlist URI: oss://your-oss-bucket-name/output/master.m3u8

  • Target video 1

    • Segment duration: 10 seconds

    • Pre-transcode duration: 36 seconds

    • Video codec: H.264

    • Resolution: 1920×1080

    • Frame rate: 25 fps

    • Audio codec: AAC

    • Audio bitrate: 128 Kbps

    • Output path prefix: oss://your-oss-bucket-name/output/1080p/1080p

  • Target video 2

    • Segment duration: 10 seconds

    • Pre-transcode duration: 36 seconds

    • Video codec: H.264

    • Resolution: 1280×720

    • Frame rate: 25 fps

    • Audio codec: AAC

    • Audio bitrate: 96 Kbps

    • Output path prefix: oss://your-oss-bucket-name/output/720p/720p

  • Target video 3

    • Segment duration: 10 seconds

    • Pre-transcode duration: 36 seconds

    • Video codec: H.264

    • Resolution: 720×540

    • Frame rate: 25 fps

    • Audio codec: AAC

    • Audio bitrate: 64 Kbps

    • Output path prefix: oss://your-oss-bucket-name/output/540p/540p

Step 1: Generate playlist

  • Request example

    {
      "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"
            }
          }
        }
      ]
    }
    
  • Response example

    {
      "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"
        }
      ]
    }
  • Sample code

    # -*- 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:
            """
            Initialize a client using AccessKey ID and AccessKey secret.
            @param access_key_id:
            @param access_key_secret:
            @return: Client
            @throws Exception
            """
            config = open_api_models.Config(
                # Your AccessKey ID.
                access_key_id=access_key_id,
                # Your AccessKey secret.
                access_key_secret=access_key_secret
            )
            # IMM endpoint.
            config.endpoint = f'imm.cn-hangzhou.aliyuncs.com'
            return imm20200930Client(config)
        @staticmethod
        def main() -> None:
            # Use IMM AccessKey ID and secret. Read from configuration if possible.
            imm_access_key_id = "yourAccessKeyId"
            imm_access_key_secret = "yourAccessKeySecret"
            # Project name.
            project_name = "test-project"
            # Source video OSS URI.
            source_uri = "oss://your-oss-bucket-name/test.avi"
            # Target URI prefix.
            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"
            # Initialize client.
            client = Sample.create_client(imm_access_key_id, imm_access_key_secret)
            # Create 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",
                    )
                ),
            )
            # Create 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",
                    )
                ),
            )
            # Create 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",
                    )
                ),
            )
            # Create API request.
            req = imm_20200930_models.GenerateVideoPlaylistRequest(
                project_name=project_name,
                source_uri=source_uri,
                master_uri=master_uri,
                targets=[target_1080p, target_720p, target_540p]
            )
            # Print request.
            print(json.dumps(req.to_map(), indent=4))
            # Send request.
            response = client.generate_video_playlist(req)
            # Print response.
            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() {
    	// Initialize IMM client.
    	immClient, err := imm.NewClient(&openapi.Config{
    		RegionId:        tea.String("cn-hangzhou"),            // Region ID of your project.
    		AccessKeyId:     tea.String("your_access_key_id"),     // RAM user AccessKey ID.
    		AccessKeySecret: tea.String("your_access_key_secret"), // RAM user AccessKey secret.
    	})
    	if err != nil {
    		// Handle error.
    		panic(err)
    	}
    	// Project name.
    	projectName := "test-project"
    	// Video OSS URI.
    	sourceUri := "oss://your-oss-bucket-name/test.avi"
    	// Target URI prefix.
    	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"),
    			},
    		},
    	}
    	// Create API request.
    	req := &imm.GenerateVideoPlaylistRequest{
    		ProjectName: tea.String(projectName),
    		SourceURI:   tea.String(sourceUri),
    		MasterURI:   tea.String(masterURI),
    		Targets:     []*imm.GenerateVideoPlaylistRequestTargets{target1080p, target720p, target540p},
    	}
    	// Send request.
    	res, err := immClient.GenerateVideoPlaylist(req)
    	if err != nil {
    		panic(err)
    	}
    	// Print response.
    	fmt.Println("Response:", *res.Body)
    }
    

Step 2: Sign the playlist

Sign the returned master playlist URL using OSS signing. See Step 2: Sign the playlist.

Step 3: Play the video

For playback instructions, see Step 3: Play the video.

FAQ

Do I need a custom player?

No. Transcode while streaming supports standard HLS protocol. Use any standard HLS-compatible player (such as the Alibaba Cloud Aliplayer or Safari browser).

What output files are generated?

We generate an m3u8 file and TS files based on the input path prefix you specify. The m3u8 file is generated immediately.

If you specify a pre-transcode duration, the system asynchronously generates corresponding TS files. Unspecified segments are transcoded on demand during playback. If a video is never played, no TS files are generated for those segments. For example, if playback starts at the 15-minute mark, transcoding begins from that point. The resulting directory structure looks like this:

.
├── outobjprefix.m3u8
├── outobjprefix-c280f054328fcde47c1732a8f2915009-0.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-1.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-2.ts
├── outobjprefix-c280f054328fcde47c1732a8f2915009-3.ts

Can I still play the video if I manually delete generated ts files?

Yes. As long as the source video and m3u8 playlist remain, deleting some or all ts files does not affect playback. When the m3u8 playlist is requested again, missing ts files are regenerated. This lets you clean up ts files for rarely viewed videos to reduce storage costs without impacting future playback.

Can I use a non-transcode-while-streaming m3u8 file for this feature?

No. You cannot use m3u8 files generated outside the transcode while streaming process to enable this feature.

Can I use CDN to accelerate transcode while streaming?

Yes. For details, see Use CDN to accelerate transcode while streaming.