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
-
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> -
Initialize the Live Editing Web SDK.
window.AliyunLiveEditor.init(config);-
The
configparameter is an object. For a description of its properties, see Config properties. -
For an example of the
init()initializer function, see init() sample code.
-
Config properties
|
Parameter |
Type |
Required |
Description |
Version introduced |
|
locale |
string |
No |
The interface language. Valid values:
|
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 |
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
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: