VOD-to-live stream using APIs

更新时间:
复制 MD 格式

Create a 24/7 live stream from your video-on-demand (VOD) files by using APIs. Combine multiple VOD files into a continuous live stream, schedule broadcasts, and insert ads in real time or at scheduled intervals to generate revenue.

How it works

image

To create a VOD-to-live stream, call the APIs for a production studio in playlist mode. The process has four steps:

  1. Enable the VOD system bucket: After you activate ApsaraVideo VOD, the system assigns an independent VOD system bucket in each service region. Enable this bucket to upload and manage your media assets.

  2. Upload audio and video files: Upload the video files that you want to stream to ApsaraVideo VOD storage. For example, upload videos A, B, and C in their playback order.

  3. Add a streaming domain: This domain provides the playback URL for your audience.

  4. Use APIs to configure the production studio: Call the APIs to specify how many times each video plays and how many times the entire episode list loops. For example, configure video A to play once, video B twice, and video C three times. Then retrieve the episode list and start the stream.

Prerequisites

  • You have created an Alibaba Cloud account and completed real-name verification.

  • ApsaraVideo VOD, ApsaraVideo Live, and the Cloud Production Studio service are activated. For more information, see Activate ApsaraVideo VOD, Activate and purchase ApsaraVideo Live, and Activate the Cloud Production Studio service.

    Note

    The production studio feature is currently available in the China (Shanghai), China (Beijing), Asia Pacific SE 1 (Singapore), and Asia Pacific SE 3 (Jakarta) regions. Support for more regions will be available in the future.

  • You have a streaming domain. To get started quickly, we recommend that you select a live center located outside the Chinese mainland and set the acceleration region to Outside Chinese Mainland. This exempts the domain from ICP filing requirements.

  • The AliyunFCFullAccess, AliyunLiveFullAccess, and AliyunVODFullAccess system policies are attached to a RAM user. For more information, see Create a RAM user and grant permissions.

Step 1. Enable the VOD system bucket

In the ApsaraVideo VOD console, choose Configuration Management > Media Management > Storage. For the VOD system bucket, click Enable.

Note

Wait until the storage address is enabled. You can use the storage address only after the system displays a The dedicated bucket is enabled. message and the storage address status is Normal.

Step 2. Upload audio and video files

  1. In the ApsaraVideo VOD console, go to the Media Files > Video/Audio page and click Upload Audio/Video .

  2. On the Upload Audio/Video page, click Add Media.

  3. In the Add Media dialog box, select From Local, choose the three video files you prepared in sequence, and then click Upload.

  4. After the upload is complete, return to the Audio/Video page to view and record the resource ID for each file. In the Actions column for each video, click More > Add to Production Studio. This makes the content available to the ApsaraVideo Live production studio. For more information about the features of a production studio, see Feature overview.

Step 3. Add a streaming domain

  1. In the ApsaraVideo Live console, go to the Domain Names page and click Add Domain.

  2. Configure the domain details and click Next. For more information about the parameters, see Add an accelerated domain name.

    For this tutorial, set Business Type to Streaming Domain, Acceleration Region to Outside Chinese Mainland, enter your Accelerated Domain Name, and set Live Center to China (Shanghai).

  3. Record the generated CNAME value for the next step.

    You must also add a CNAME record with your DNS provider to point the host record to the CNAME value. This enables CDN acceleration.

  4. On the Alibaba Cloud DNS page, find the domain you want to configure and click Settings in the Actions column.

  5. Click Add Record, complete the CNAME configuration, and click Confirm. For more information, see Configure a CNAME record for a domain name.

    Set Record Type to CNAME, Host to @, and Resolution Line to Default. In the Record Value field, enter the CNAME target address. Set TTL to 10 Minutes.

Step 4. Configure the production studio with APIs

  1. Open IntelliJ IDEA and create a Maven project. In the pom.xml file, create a <dependencies></dependencies> tag and add the following dependencies.

    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>live20161101</artifactId>
        <version>2.0.0</version>
     </dependency>
     <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
     </dependency>
  2. In the src/main/java directory of your project, right-click the java folder and create a new Java class. For this example, name it Bodan.

  3. Configure the parameters in the following sample code and run it.

    package com.alibaba.aliyundebug.common;
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.aliyun.live20161101.Client;
    import com.aliyun.live20161101.models.*;
    import com.aliyun.teaopenapi.models.Config;
    import org.apache.commons.codec.digest.DigestUtils;
    import java.util.List;
    import java.util.Random;
    import java.util.UUID;
    public class Bodan {
        private final static String ACCESS_KEY_ID = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        private final static String ACCESS_KEY_SECRET = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        private static class LiveClient {
            private static volatile Client instance;
            private LiveClient() {
            }
            public static Client getInstance(String endpoint, String accessKeyId, String accessKeySecret) {
                if (instance == null) {
                    synchronized (LiveClient.class) {
                        if (instance == null) {
                            try {
                                Config config = new Config();
                                config.setEndpoint(endpoint);
                                config.setAccessKeyId(accessKeyId);
                                config.setAccessKeySecret(accessKeySecret);
                                instance = new Client(config);
                            } catch (Exception e) {
                                throw new RuntimeException("Live client initialization failed: " + e.getMessage(), e);
                            }
                        }
                    }
                }
                return instance;
            }
        }
        private static CreateCasterResponse createCaster(Client client) throws Exception {
            CreateCasterRequest request = new CreateCasterRequest();
            Random random = new Random();
            int i = random.nextInt(100000);
            request.setCasterName("casterName" + i);
            UUID uuid = UUID.randomUUID();
            String token = "thisIsaToken";
            String clientToken = DigestUtils.sha256Hex(token + uuid);
            request.setClientToken(clientToken);
            // To use an episode list, the production studio must be in playlist mode.
            request.setNormType(6);
            request.setChargeType("PostPaid");
            CreateCasterResponse response = client.createCaster(request);
            System.out.println("The production studio is created. Response: " + JSON.toJSONString(response));
            return response;
        }
        private static void setCasterConfig(Client client, String casterId,String domainName) throws Exception {
            SetCasterConfigRequest request = new SetCasterConfigRequest();
            request.setCasterId(casterId);
            // Configure the domain name.
            request.setDomainName(domainName);
            JSONObject transcodeConfig = new JSONObject();
            JSONArray liveTemplate = new JSONArray();
            // Configure a template for the production studio.
            liveTemplate.add("lld");
            transcodeConfig.put("LiveTemplate", liveTemplate);
            // Configure a transcoding template.
            transcodeConfig.put("CasterTemplate", "lp_sd");
            request.setTranscodeConfig(transcodeConfig.toJSONString());
            SetCasterConfigResponse response = client.setCasterConfig(request);
            System.out.println("The production studio is configured. Response: " + JSON.toJSONString(response));
        }
        private static StartCasterResponse startCaster(Client client, String casterId) throws Exception {
            StartCasterRequest startCasterRequest = new StartCasterRequest();
            startCasterRequest.setCasterId(casterId);
            StartCasterResponse acsResponse = client.startCaster(startCasterRequest);
            System.out.println("The production studio is started.");
            return acsResponse;
        }
        private static StopCasterResponse stopCaster(Client client, String casterId) throws Exception {
            StopCasterRequest stopCasterRequest = new StopCasterRequest();
            stopCasterRequest.setCasterId(casterId);
            StopCasterResponse acsResponse = client.stopCaster(stopCasterRequest);
            System.out.println("The production studio is stopped.");
            return acsResponse;
        }
        private static AddShowIntoShowListResponse addShowIntoShowList(Client client, String showName, String resourceId, String resourceUrl,
                                                                       String resourceType, Integer spot, Integer repeatTimes,
                                                                       String casterId, Long duration) throws Exception {
            AddShowIntoShowListRequest addShowIntoShowListRequest = new AddShowIntoShowListRequest();
            if (casterId == null || resourceType == null) {
                return null;
            }
            if (resourceId == null && resourceUrl == null) {
                return null;
            }
            addShowIntoShowListRequest.setCasterId(casterId);
            addShowIntoShowListRequest.setResourceType(resourceType);
            if (showName != null) {
                addShowIntoShowListRequest.setShowName(showName);
            }
            if (resourceUrl != null) {
                addShowIntoShowListRequest.setResourceUrl(resourceUrl);
            }
            if (resourceId != null) {
                addShowIntoShowListRequest.setResourceId(resourceId);
            }
            if (spot != null) {
                addShowIntoShowListRequest.setSpot(spot);
            }
            if (repeatTimes != null) {
                addShowIntoShowListRequest.setRepeatTimes(repeatTimes);
            }
            if (duration != null) {
                addShowIntoShowListRequest.setDuration(duration);
            }
            return client.addShowIntoShowList(addShowIntoShowListRequest);
        }
        private static void removeShowFromShowList(Client client, String casterId, String showId) throws Exception {
            RemoveShowFromShowListRequest removeShowFromShowList = new RemoveShowFromShowListRequest();
            removeShowFromShowList.setShowId(showId);
            removeShowFromShowList.setCasterId(casterId);
            RemoveShowFromShowListResponse removeShowFromShowListFromShowListResponse = client.removeShowFromShowList(removeShowFromShowList);
            System.out.println("The show is removed from the production studio. Response: " + JSON.toJSONString(removeShowFromShowListFromShowListResponse));
        }
        private static void modifyShowList(Client client, String casterId, String showId, Integer repeatTimes, Integer spot,
                                                             String highPriorityShowId, String highPriorityShowStartTime) throws Exception {
            ModifyShowListRequest modifyShowListRequest = new ModifyShowListRequest();
            if (casterId != null) {
                modifyShowListRequest.setCasterId(casterId);
            }
            if (showId != null) {
                modifyShowListRequest.setShowId(showId);
            }
            if (repeatTimes != null) {
                modifyShowListRequest.setRepeatTimes(repeatTimes);
            }
            if (spot != null) {
                modifyShowListRequest.setSpot(spot);
            }
            if (highPriorityShowId != null) {
                modifyShowListRequest.setHighPriorityShowId(highPriorityShowId);
            }
            if (highPriorityShowStartTime != null) {
                modifyShowListRequest.setHighPriorityShowStartTime(highPriorityShowStartTime);
            }
            ModifyShowListResponse modifyShowListResponse = client.modifyShowList(modifyShowListRequest);
            System.out.println("The episode list is modified. Response: " + JSON.toJSONString(modifyShowListResponse));
        }
        private static void describeShowList(Client client, String casterId) throws Exception {
            DescribeShowListRequest describeShowListRequest = new DescribeShowListRequest();
            if (casterId != null) {
                describeShowListRequest.setCasterId(casterId);
            }
            DescribeShowListResponse describeShowListRequestResponse = client.describeShowList(describeShowListRequest);
            System.out.println("The query for the episode list is successful. Response: " + JSON.toJSONString(describeShowListRequestResponse));
            DescribeShowListResponseBody showListBody = describeShowListRequestResponse.getBody();
            JSONObject showList = JSON.parseObject(showListBody.getShowList());
            JSONArray shows = showList.getJSONArray("Shows");
            // Print the episode list.
            for (int i = 0; i < shows.size(); i++) {
                JSONObject show = (JSONObject) shows.get(i);
                String showId = show.getString("ShowId");
                String resourceType = show.getString("ResourceType");
                String resourceInfo = show.getString("ResourceInfo");
                Integer repeatTimes = show.getInteger("RepeatTimes");
                Long duration = show.getLong("Duration");
                String showInfo = String.format("show%d: showId: %s \n resourceType: %s  \n  resourceInfo: %s \n RepeatTimes: %d \n Duration: %d",
                        i + 1, showId, resourceType, resourceInfo, repeatTimes, duration);
                System.out.println(showInfo);
            }
        }
        private static void playChoosenShow(Client client, String casterId, String showId) throws Exception {
            PlayChoosenShowRequest playChoosenShow = new PlayChoosenShowRequest();
            playChoosenShow.setCasterId(casterId);
            playChoosenShow.setShowId(showId);
            PlayChoosenShowResponse playChoosenShowResponse = client.playChoosenShow(playChoosenShow);
            System.out.println("Successfully switched to showId: " + showId);
        }
        private static List<DescribeCasterStreamUrlResponseBody.DescribeCasterStreamUrlResponseBodyCasterStreamsCasterStream> describeCasterStreamUrl(Client client, String casterId) throws Exception {
            DescribeCasterStreamUrlRequest describeCasterStreamUrlRequest = new DescribeCasterStreamUrlRequest();
            describeCasterStreamUrlRequest.setCasterId(casterId);
            DescribeCasterStreamUrlResponse response = client.describeCasterStreamUrl(describeCasterStreamUrlRequest);
            return response.getBody().getCasterStreams().getCasterStream();
        }
        public static void main(String[] args) throws Exception {
            Client client = LiveClient.getInstance("live.aliyuncs.com", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            // Create a production studio.
            CreateCasterResponse caster = createCaster(client);
            String casterId = caster.getBody().getCasterId();
            // Configure the production studio.
            String domainName = "example.aliyundoc.com"; // Set the domain name.
            setCasterConfig(client, casterId,domainName);
            // Add three VOD files. The first file plays once, the second twice, and the third three times.
            String[] resourceIds = new String[]{"698d2b23581f476ea71107703e64****", "9c97e83e211a435b9f797e4e20ee****", "76c6addaa41c438985666a8a964f****"};
            for (int i = 0; i < resourceIds.length; i++) {
                String showName = "ShowName#" + i;
                Integer repeatTimes = i;
                addShowIntoShowList(client, showName, resourceIds[i], null, "vod", null, repeatTimes, casterId, null);
            }
            modifyShowList(client, casterId, null, 10, null, null, null);
            describeShowList(client, casterId);
            startCaster(client, casterId);
            Thread.sleep(500000);
            stopCaster(client, casterId);
        }
    }

    Parameter descriptions:

    Parameter

    Description

    private final static String ACCESS_KEY_ID = "Your AccessKey ID";
    private final static String ACCESS_KEY_SECRET = "Your AccessKey secret";

    An AccessKey pair is used for identity verification. It consists of an AccessKey ID and an AccessKey secret.

    • AccessKey ID: identifies the user.

    • AccessKey secret: authenticates the user. Keep your AccessKey secret confidential.

    For more information, see Create an AccessKey pair.

    request.setDomainName("example.aliyundoc.com");

    The streaming domain.

    String[] resourceIds = new String[]{"698d2b23581f476ea71107703e64****", "9c97e83e211a435b9f797e4e20ee****", "76c6addaa41c438985666a8a964f****"};

    The resource IDs. See Step 2. Upload audio and video files to obtain them.

  4. View the execution result.

    Sample result:

    "C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
    The production studio is created. Response: {"casterId":"87564f62-8c51-4xxx","requestId":"853D754D-440A-5743-xxx"}
    The production studio is configured. Response:{"casterId":"87564f62-8c3xxx","requestId":"4727BCE9-2058-5xxx"}
    The episode list is modified. Response: {"data":"{\"RequestId\":\"1B2E6CCF-7726-5xxx\",xxx}","httpResponse":{"encoding":"UTF-8","headers":{"Keep-Alive":"timeout=25","Access-Control-xxx"}}}
    The query for the episode list is successful. Response: {"data":"{\"RequestId\":\"CCE3BF90-E6A5-xxx\",\"ShowListInfo\":{\"TotalShowListRepeatTimes\":10,\"ShowListRepeatTimes\":10,\"ShowList\":xxx}}"}
    show1: showId: 69548057-i7z xxx
        resourceType: null
        resourceInfo: {"resourceId":"908xxx","resourceUrl":"https://outin-f7/07xxx-xxx-22ef7"}
        RepeatTimes: 0
  5. On the Production Studios page, find the production studio you created and click Open in the Actions column. You can see the three VOD files added to the episode list, playing sequentially as configured.

Next steps

To play the stream, click Streaming URL in the production studio and copy the URL. Use a media player such as VLC, a live streaming demo, or a player SDK for playback. For more information, see Live stream playback.

The Streaming URL dialog box provides URLs grouped by resolution, such as Original and lld. Each group includes playback URLs for FLV, RTMP, M3U8, and RTS protocols. Copy the URL for the protocol you want to use.