Integrate the Live Editing Web SDK

更新时间:
复制 MD 格式

Intelligent Media Production lets you stream and edit time-sensitive content simultaneously. Integrate the Live Editing Web SDK to embed this capability in your frontend application.

Usage notes

The Live Editing Web SDK version 1.1.2 referenced in this topic is for illustration only. For the latest version, see Live Editing Project - Help Information.

Procedure

  1. Import the Live Editing Web SDK.

    In the <head> tag of the frontend page file of your project, import the CSS file for the Live Editing Web SDK.

    <head>
      <link rel="stylesheet" href="https://g.alicdn.com/thor-server/live-editing-websdk/1.1.2/index.css">
    </head>

    In the <body> tag, add a <div> node to mount the editing interface. At the end of the <body> tag, import the JS file of the Web SDK and add a <script> node to call the Web SDK.

    <body>
      <div id="aliyun-live-editor" style="height:700px"></div> // You can change the container height as needed.
      <script src="https://g.alicdn.com/thor-server/live-editing-websdk/1.1.2/index.js"></script>
      <script>
        // Place the code to call the SDK here.
      </script>
    </body>
  2. Initialize the Live Editing Web SDK.

    window.AliyunLiveEditor.init(config);

Config properties

Parameter

Type

Required

Description

Version introduced

locale

string

No

The interface language. Valid values:

  • zh-CN (default): Chinese.

  • en-US: English.

1.0.0

container

Element

Yes

The DOM node where the Web SDK interface is mounted.

1.0.0

projectId

string

Yes

The ID of the live editing project.

1.0.0

onBackButtonClick

() => void;

No

Callback for the back button in the upper-left corner. If not specified, the button is hidden.

1.0.0

updateEditingProject

(req: { ProjectId: string; Title: string }) => Promise<void>;

No

Callback to modify the editing project title. If not specified, the title is read-only. For more information, see UpdateEditingProject.

1.0.0

getEditingProject

(req: { ProjectId: string }) => Promise<Response<GetEditingProjectRsp>>;

Yes

Retrieves editing project metadata, such as the title and save path. For more information, see GetEditingProject.

1.0.0

getEditingProjectMaterials

(req: { ProjectId: string }) => Promise<Response<GetEditingProjectMaterialsRsp>>;

Yes

Retrieves the live streams and segments associated with the live editing project. For more information, see GetEditingProjectMaterials.

1.0.0

getLiveEditingIndexFile

(req: { ProjectId: string; DomainName: string; AppName: string; StreamName: string }) => Promise<Response<{ IndexFile: string }>>;

Yes

Retrieves the playback URL of the recorded live stream. For more information, see GetLiveEditingIndexFile.

1.0.0

describeLiveDomainConfigs

(req: { DomainName: string; FunctionNames: string }) => Promise<Response<DomainConfigs>>;

Yes

Queries the configurations of live streaming domain names. For more information, see DescribeLiveDomainConfigs.

1.0.0

submitLiveEditingJob

(req: SubmitLiveEditingJobReq) => Promise<Response<{ MediaId: string }>>;

Yes

Submits a job to synthesize video clips. For more information, see SubmitLiveEditingJob.

1.0.0

getMediaInfo

(req: { MediaId: string }) => Promise<Response<{ MediaInfo: MediaInfo }>>;

Yes

Queries the status of a synthesized video clip. For more information, see GetMediaInfo.

1.0.0

onExport

(segments: Segment[]) => void;

Yes

Callback for the Export to Video Editing button in the upper-right corner. The segments parameter contains the array of selected video clips.

1.0.0

getDescribeLiveSnapshotConfig

(req: { DomainName: string; AppName: string }) => Promise<Response<GetDescribeLiveSnapshotConfigList>>;

No

Queries the live snapshot configurations. For more information, see DescribeLiveSnapshotConfig.

1.1.0

getDescribeLiveStreamSnapshotInfo

(req: { DomainName: string; AppName: string; StreamName: string; StartTime: string; EndTime: string; Limit: number; Order: string }) => Promise<Response<LiveStreamSnapshotInfoList>>;

No

Queries snapshot content. For more information, see DescribeLiveStreamSnapshotInfo.

1.1.0

batchGenOSSUrlWithSign

(req: { signList: SnapshotOssInfo[] }) => Promise<Response<SignedUrl[]>>;

No

Generates signed URLs for OSS resources in batches. A signed URL is an OSS URL with an embedded access token.

Note

If snapshots are stored in a private bucket, implement a server-side API to generate signed URLs for OSS resources in batches. Be aware of the TTL for signed URLs. For more information, see Signature Version 1.

1.1.2

Data structures:

  • Segment

    interface Segment {
      title: string; // The title of the video clip.
      mediaId: string; // The media asset ID of the video clip.
      coverUrl: string | null; // The thumbnail URL of the video clip. This can be null.
      duration: number; // The duration of the video clip in milliseconds.
    }
  • SnapshotOssInfo

    interface SnapshotOssInfo {
      region: string; // The region.
      bucketName: string; // The name of the OSS bucket.
      objectName: string; // The name of the file stored in OSS, such as path/to/object.*.
    }

init() sample code

Important

The Web SDK handles only UI interactions and does not initiate API requests. You must implement your own request logic: send requests to your server, which then forwards them to the corresponding Alibaba Cloud OpenAPI using your AccessKey ID and AccessKey secret.

// Note: The Web SDK does not provide the request method. This is just an example. You can use your preferred network request library, such as axios.

const projectId = 'exampleId';

window.AliyunLiveEditor.init({
  locale: 'en-US',
  container: document.getElementById('aliyun-live-editor'),
  projectId,
  onBackButtonClick: () => {
    // Redirect to the list page.
    window.location.href = '/mediaEdit/list/live';
  },
  updateEditingProject: req => {
    return request('UpdateEditingProject', req);
  },
  getEditingProject: req => {
    return request('GetEditingProject', req);
  },
  getEditingProjectMaterials: req => {
    return request('GetEditingProjectMaterials', req);
  },
  getLiveEditingIndexFile: req => {
    return request('GetLiveEditingIndexFile', req);
  },
  describeLiveDomainConfigs: req => {
    return request('DescribeLiveDomainConfigs', req);
  },
  submitLiveEditingJob: req => {
    return request('SubmitLiveEditingJob', req);
  },
  getMediaInfo: req => {
    return request('GetMediaInfo', req);
  },
  getDescribeLiveSnapshotConfig: req => {
    return request('DescribeLiveSnapshotConfig', req);
  },
  getDescribeLiveStreamSnapshotInfo: req => {
    return request('DescribeLiveStreamSnapshotInfo', req);
  },
  batchGenOSSUrlWithSign: req => {
    return request('multiGenerateOSSURLWithSign', req); // https://help.aliyun.com/document_detail/31952.htm
  },
  onExport: async segments => {
    const { ProjectMaterials = [] } = await request('GetEditingProjectMaterials', {
      ProjectId: projectId
    }).then(res => res.data);
    let videoEditingProjectId;
    if (ProjectMaterials.length) {
      // A video editing project is already attached.
      videoEditingProjectId = ProjectMaterials[0];
    } else {
      // Create a new standard editing project.
      const { Project } = await request('CreateEditingProject', {
        Title: `Live_Editing_Video_${projectId}`,
      }).then(res => res.data);
      // Attach the live editing project to the standard editing project.
      await request('AddEditingProjectMaterials', {
        ProjectId: projectId,
        MaterialMaps: JSON.stringify({ editingProject: Project.ProjectId })
      });
      videoEditingProjectId = Project.ProjectId;
    }

    const mediaIds = segments.map(s => s.mediaId);

    await handleBindingMaterials(mediaIds, videoEditingProjectId);

    // Open the page for the standard editing project.
    window.open(`/mediaEdit/detail/${videoEditingProjectId}`);
  },
});

// The API for adding and attaching materials has a limit of 10 items per request. Perform the operation in batches.
async function handleBindingMaterials(MediaIds, ProjectId) {
  const promiseGroup = [];

  const addTimes = Math.ceil(MediaIds.length / 10);
  for (let i = 0; i < addTimes; i++) {
    const newMap = {};
    const videoList = MediaIds.slice(i * 10, (i + 1) * 10);

    if (videoList.length) {
      newMap.video = videoList.join(',');
    }

    promiseGroup.push(
      request('AddEditingProjectMaterials', {
        ProjectId,
        MaterialMaps: JSON.stringify(newMap)
      })
    );
  }

  await Promise.all(promiseGroup);
};

Related API operations: