trtc-electron-sdk 12.5.705-beta.0 → 12.6.705
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/liteav/Live/Pusher/index.d.ts +16 -1
- package/liteav/Live/Pusher/index.js +27 -1
- package/liteav/Live/live_define.d.ts +75 -0
- package/liteav/Live/live_define.js +99 -1
- package/liteav/MediaMixingDesigner/index.d.ts +10 -7
- package/liteav/MediaMixingDesigner/index.js +103 -75
- package/liteav/constant.d.ts +1 -0
- package/liteav/constant.js +4 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/BaseStreamLayoutManager.d.ts +27 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/BaseStreamLayoutManager.js +99 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/CustomStreamLayoutManager.d.ts +11 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/CustomStreamLayoutManager.js +119 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/NoneStreamLayoutManager.d.ts +11 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/NoneStreamLayoutManager.js +64 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/index.d.ts +7 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/index.js +34 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/types.d.ts +21 -0
- package/liteav/extensions/MediaMixingManager/StreamLayout/types.js +2 -0
- package/liteav/extensions/MediaMixingManager/index.d.ts +204 -38
- package/liteav/extensions/MediaMixingManager/index.js +447 -36
- package/liteav/extensions/MediaMixingManager/types.d.ts +100 -0
- package/liteav/extensions/MediaMixingManager/types.js +26 -0
- package/liteav/utils.d.ts +27 -0
- package/liteav/utils.js +85 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { V2LiveRotation, V2LiveFillMode, V2LiveAudioQuality, V2LiveVideoEncoderParam, V2LiveMirrorType, V2LiveMode, V2LivePusherEvent } from '../live_define';
|
|
1
|
+
import { V2LiveRotation, V2LiveFillMode, V2LiveAudioQuality, V2LiveVideoEncoderParam, V2LiveMirrorType, V2LiveMode, V2LivePusherEvent, V2TXLiveTranscodingConfig } from '../live_define';
|
|
2
|
+
import { TRTCCameraCaptureParams } from '../../trtc_define';
|
|
2
3
|
import { TRTCDeviceInfo, TRTCDeviceType } from '../../trtc_define';
|
|
3
4
|
/**
|
|
4
5
|
* 腾讯云直播推流器
|
|
@@ -183,6 +184,13 @@ export declare class V2LivePusher {
|
|
|
183
184
|
* @return {Number} - 参考 V2LiveCode 的定义
|
|
184
185
|
*/
|
|
185
186
|
enableVolumeEvaluation(intervalMs: number): number;
|
|
187
|
+
/**
|
|
188
|
+
* 设置云端的混流转码参数
|
|
189
|
+
*
|
|
190
|
+
* @param {V2TXLiveTranscodingConfig | null} config - 混流转码参数,参考 V2TXLiveTranscodingConfig 的定义。如果传入 null 则取消云端混流转码。
|
|
191
|
+
* @return {Number}
|
|
192
|
+
*/
|
|
193
|
+
setMixTranscodingConfig(config: V2TXLiveTranscodingConfig | null): number;
|
|
186
194
|
/**
|
|
187
195
|
* 获取摄像头设备列表
|
|
188
196
|
*
|
|
@@ -330,9 +338,16 @@ export declare class V2LivePusher {
|
|
|
330
338
|
* - false: 不跟随。只有当 SDK 使用的音频设备被移除后或插入新的音频设备为系统默认设备时,SDK 才切换至系统默认的音频设备。
|
|
331
339
|
*/
|
|
332
340
|
enableFollowingDefaultAudioDevice(deviceType: TRTCDeviceType, enable: boolean): void;
|
|
341
|
+
/**
|
|
342
|
+
* 设置摄像头采集偏好
|
|
343
|
+
*
|
|
344
|
+
* @param {TRTCCameraCaptureParams} params - 摄像头采集参数
|
|
345
|
+
*/
|
|
346
|
+
setCameraCapturerParam(params: TRTCCameraCaptureParams): void;
|
|
333
347
|
private enableCustomVideoRender;
|
|
334
348
|
private _createPusherRender;
|
|
335
349
|
private _destroyPusherRender;
|
|
350
|
+
private _destroyCameraTestRender;
|
|
336
351
|
private _setVideoRenderBuffer;
|
|
337
352
|
private _addVideoRenderCallback;
|
|
338
353
|
private _removeVideoRenderCallback;
|
|
@@ -60,7 +60,7 @@ class V2LivePusher {
|
|
|
60
60
|
}
|
|
61
61
|
destroy() {
|
|
62
62
|
this._destroyPusherRender();
|
|
63
|
-
this.
|
|
63
|
+
this._destroyCameraTestRender();
|
|
64
64
|
this.livePusher.destroy();
|
|
65
65
|
this.livePusher = null;
|
|
66
66
|
this.deviceManager = null;
|
|
@@ -297,6 +297,17 @@ class V2LivePusher {
|
|
|
297
297
|
this.logger.debug(`enableVolumeEvaluation, intervalMs:${intervalMs}`);
|
|
298
298
|
return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.enableVolumeEvaluation(intervalMs);
|
|
299
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* 设置云端的混流转码参数
|
|
302
|
+
*
|
|
303
|
+
* @param {V2TXLiveTranscodingConfig | null} config - 混流转码参数,参考 V2TXLiveTranscodingConfig 的定义。如果传入 null 则取消云端混流转码。
|
|
304
|
+
* @return {Number}
|
|
305
|
+
*/
|
|
306
|
+
setMixTranscodingConfig(config) {
|
|
307
|
+
var _a;
|
|
308
|
+
this.logger.debug(`setMixTranscodingConfig, config:${config}`);
|
|
309
|
+
return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setMixTranscodingConfig(config);
|
|
310
|
+
}
|
|
300
311
|
/////////////////////////////////////////////////////////////////////////////////
|
|
301
312
|
//
|
|
302
313
|
// (二)deviceManager相关接口函数
|
|
@@ -516,6 +527,16 @@ class V2LivePusher {
|
|
|
516
527
|
this.logger.debug(`enableFollowingDefaultAudioDevice, deviceType:${deviceType}, enable:${enable}`);
|
|
517
528
|
this.deviceManager.enableFollowingDefaultAudioDevice(deviceType, enable);
|
|
518
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* 设置摄像头采集偏好
|
|
532
|
+
*
|
|
533
|
+
* @param {TRTCCameraCaptureParams} params - 摄像头采集参数
|
|
534
|
+
*/
|
|
535
|
+
setCameraCapturerParam(params) {
|
|
536
|
+
var _a;
|
|
537
|
+
this.logger.debug(`setCameraCapturerParam, params:${JSON.stringify(params)}`);
|
|
538
|
+
(_a = this.deviceManager) === null || _a === void 0 ? void 0 : _a.setCameraCapturerParam(params);
|
|
539
|
+
}
|
|
519
540
|
////////////////////////////////////////////////////////////////////////////////
|
|
520
541
|
//
|
|
521
542
|
// 内部接口
|
|
@@ -542,6 +563,11 @@ class V2LivePusher {
|
|
|
542
563
|
this._removeVideoRenderCallback();
|
|
543
564
|
this.enableCustomVideoRender(false, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer);
|
|
544
565
|
}
|
|
566
|
+
_destroyCameraTestRender() {
|
|
567
|
+
if (this.cameraTestVideoRender) {
|
|
568
|
+
this.stopCameraDeviceTest();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
545
571
|
// videoRender callback and buffer
|
|
546
572
|
_setVideoRenderBuffer() {
|
|
547
573
|
var _a;
|
|
@@ -310,3 +310,78 @@ export declare enum V2LivePushStatus {
|
|
|
310
310
|
V2LivePushStatusConnectSuccess = 2,
|
|
311
311
|
V2LivePushStatusReconnecting = 3
|
|
312
312
|
}
|
|
313
|
+
export declare enum V2TXLiveMixInputType {
|
|
314
|
+
V2TXLiveMixInputTypeAudioVideo = 0,
|
|
315
|
+
V2TXLiveMixInputTypePureVideo = 1,
|
|
316
|
+
V2TXLiveMixInputTypePureAudio = 2
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* 云端混流中每一路子画面的位置信息
|
|
320
|
+
*
|
|
321
|
+
* @param {String} userId - 参与混流的 userId
|
|
322
|
+
* @param {String} streamId - 参与混流的 userId 所在对应的推流 streamId, 空的话表示当前推流 streamId。
|
|
323
|
+
* @param {Number} x - 图层位置 x 坐标(绝对像素值)。
|
|
324
|
+
* @param {Number} y - 图层位置 y 坐标(绝对像素值)。
|
|
325
|
+
* @param {Number} width - 图层位置宽度(绝对像素值)。
|
|
326
|
+
* @param {Number} height - 图层位置高度(绝对像素值)。
|
|
327
|
+
* @param {Number} zOrder - 图层层次(1 - 15)不可重复。
|
|
328
|
+
* @param {V2TXLiveMixInputType} inputType - 该直播流的输入类型。
|
|
329
|
+
*/
|
|
330
|
+
export declare class V2TXLiveMixStream {
|
|
331
|
+
userId: string;
|
|
332
|
+
streamId: string;
|
|
333
|
+
x: number;
|
|
334
|
+
y: number;
|
|
335
|
+
width: number;
|
|
336
|
+
height: number;
|
|
337
|
+
zOrder: number;
|
|
338
|
+
inputType: V2TXLiveMixInputType;
|
|
339
|
+
constructor(userId?: string, streamId?: string, x?: number, y?: number, width?: number, height?: number, zOrder?: number, inputType?: V2TXLiveMixInputType);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* 云端混流(转码)配置
|
|
343
|
+
*
|
|
344
|
+
* @param {Number} videoWidth - 【字段含义】最终转码后的视频分辨率的宽度。<br>
|
|
345
|
+
* 【推荐取值】推荐值:360px ,如果你是纯音频推流,请将 width × height 设为 0px × 0px,否则混流后会携带一条画布背景的视频流。
|
|
346
|
+
* @param {Number} videoHeight - 【字段含义】最终转码后的视频分辨率的高度。<br>
|
|
347
|
+
* 【推荐取值】推荐值:640px ,如果你是纯音频推流,请将 width × height 设为 0px × 0px,否则混流后会携带一条画布背景的视频流。
|
|
348
|
+
* @param {Number} videoBitrate - 【字段含义】最终转码后的视频分辨率的码率(kbps)<br>
|
|
349
|
+
* 【推荐取值】如果填0,后台会根据videoWidth和videoHeight来估算码率,您也可以参考枚举定义TRTCVideoResolution_640_480的注释。
|
|
350
|
+
* @param {Number} videoFramerate - 【字段含义】最终转码后的视频分辨率的帧率(FPS)<br>
|
|
351
|
+
* 【推荐取值】默认值:15fps,取值范围是 (0,30]。
|
|
352
|
+
* @param {Number} videoGOP - 【字段含义】最终转码后的视频分辨率的关键帧间隔(又称为 GOP)。<br>
|
|
353
|
+
* 【推荐取值】默认值:2,单位为秒,取值范围是 [1,8]。
|
|
354
|
+
* @param {Number} backgroundColor - 【字段含义】混合后画面的底色颜色,默认为黑色,格式为十六进制数字,比如:“0x61B9F1” 代表 RGB 分别为(97,158,241)。<br>
|
|
355
|
+
* 【推荐取值】默认值:0x000000,黑色
|
|
356
|
+
* @param {String} backgroundImage - 【字段含义】混合后画面的背景图。<br>
|
|
357
|
+
* 【推荐取值】默认值:'',即不设置背景图<br>
|
|
358
|
+
* 【特别说明】背景图需要您事先在 “[控制台](https://console.cloud.tencent.com/trtc) => 应用管理 => 功能配置 => 素材管理” 中上传,<br>
|
|
359
|
+
* 上传成功后可以获得对应的“图片ID”,然后将“图片ID”转换成字符串类型并设置到 backgroundImage 里即可。<br>
|
|
360
|
+
* 例如:假设“图片ID” 为 63,可以设置 backgroundImage = @"63";
|
|
361
|
+
* @param {Number} audioSampleRate - 【字段含义】最终转码后的音频采样率。<br>
|
|
362
|
+
* 【推荐取值】默认值:48000Hz。支持12000HZ、16000HZ、22050HZ、24000HZ、32000HZ、44100HZ、48000HZ。
|
|
363
|
+
* @param {Number} audioBitrate - 【字段含义】最终转码后的音频码率。<br>
|
|
364
|
+
* 【推荐取值】默认值:64kbps,取值范围是 [32,192]。
|
|
365
|
+
* @param {Number} audioChannels - 【字段含义】最终转码后的音频声道数<br>
|
|
366
|
+
* 【推荐取值】默认值:1。取值范围为 [1,2] 中的整型。
|
|
367
|
+
* @param {V2TXLiveMixStream[]} mixStreams - 【字段含义】每一路子画面的位置信息
|
|
368
|
+
* @param {String} outputStreamId - 【字段含义】输出到 CDN 上的直播流 ID。<br>
|
|
369
|
+
* 如不设置该参数,SDK 会执行默认逻辑,即房间里的多路流会混合到该接口调用者的视频流上,也就是 A+B =>A;<br>
|
|
370
|
+
* 如果设置该参数,SDK 会将房间里的多路流混合到您指定的直播流 ID 上,也就是 A+B =>C。<br>
|
|
371
|
+
* 【推荐取值】默认值:'',即房间里的多路流会混合到该接口调用者的视频流上。
|
|
372
|
+
*/
|
|
373
|
+
export declare class V2TXLiveTranscodingConfig {
|
|
374
|
+
videoWidth: number;
|
|
375
|
+
videoHeight: number;
|
|
376
|
+
videoBitrate: number;
|
|
377
|
+
videoFramerate: number;
|
|
378
|
+
videoGOP: number;
|
|
379
|
+
backgroundColor: number;
|
|
380
|
+
backgroundImage: string;
|
|
381
|
+
audioSampleRate: number;
|
|
382
|
+
audioBitrate: number;
|
|
383
|
+
audioChannels: number;
|
|
384
|
+
mixStreams: V2TXLiveMixStream[];
|
|
385
|
+
outputStreamId: string;
|
|
386
|
+
constructor(videoWidth?: number, videoHeight?: number, videoBitrate?: number, videoFramerate?: number, videoGOP?: number, backgroundColor?: number, backgroundImage?: string, audioSampleRate?: number, audioBitrate?: number, audioChannels?: number, mixStreams?: any[], outputStreamId?: string);
|
|
387
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* V2Live 关键类型定义
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.V2LivePushStatus = exports.V2LivePlayerStatistics = exports.V2LivePusherStatistics = exports.V2LiveAudioQuality = exports.V2LiveBufferType = exports.V2LivePixelFormat = exports.V2LiveRotation = exports.V2LiveFillMode = exports.V2LiveMirrorType = exports.V2LiveVideoEncoderParam = exports.V2LiveVideoResolutionMode = exports.V2LiveVideoResolution = exports.V2LivePlayerEvent = exports.V2LivePusherEvent = exports.V2LiveMode = exports.V2LiveCode = void 0;
|
|
6
|
+
exports.V2TXLiveTranscodingConfig = exports.V2TXLiveMixStream = exports.V2TXLiveMixInputType = exports.V2LivePushStatus = exports.V2LivePlayerStatistics = exports.V2LivePusherStatistics = exports.V2LiveAudioQuality = exports.V2LiveBufferType = exports.V2LivePixelFormat = exports.V2LiveRotation = exports.V2LiveFillMode = exports.V2LiveMirrorType = exports.V2LiveVideoEncoderParam = exports.V2LiveVideoResolutionMode = exports.V2LiveVideoResolution = exports.V2LivePlayerEvent = exports.V2LivePusherEvent = exports.V2LiveMode = exports.V2LiveCode = void 0;
|
|
7
7
|
/////////////////////////////////////////////////////////////////////////////////
|
|
8
8
|
//
|
|
9
9
|
// V2 错误码和警告码
|
|
@@ -552,3 +552,101 @@ var V2LivePushStatus;
|
|
|
552
552
|
V2LivePushStatus[V2LivePushStatus["V2LivePushStatusConnectSuccess"] = 2] = "V2LivePushStatusConnectSuccess";
|
|
553
553
|
V2LivePushStatus[V2LivePushStatus["V2LivePushStatusReconnecting"] = 3] = "V2LivePushStatusReconnecting";
|
|
554
554
|
})(V2LivePushStatus = exports.V2LivePushStatus || (exports.V2LivePushStatus = {}));
|
|
555
|
+
/////////////////////////////////////////////////////////////////////////////////
|
|
556
|
+
//
|
|
557
|
+
// (五)云端混流结构定义
|
|
558
|
+
//
|
|
559
|
+
/////////////////////////////////////////////////////////////////////////////////
|
|
560
|
+
/**
|
|
561
|
+
* 混流输入类型配置
|
|
562
|
+
*
|
|
563
|
+
* @enum {Number}
|
|
564
|
+
*/
|
|
565
|
+
const V2TXLiveMixInputType_HACK_JSDOC = {
|
|
566
|
+
/** 混入音视频。 */
|
|
567
|
+
V2TXLiveMixInputTypeAudioVideo: 0,
|
|
568
|
+
/** 只混入视频。 */
|
|
569
|
+
V2TXLiveMixInputTypePureVideo: 1,
|
|
570
|
+
/** 只混入音频。 */
|
|
571
|
+
V2TXLiveMixInputTypePureAudio: 2,
|
|
572
|
+
};
|
|
573
|
+
var V2TXLiveMixInputType;
|
|
574
|
+
(function (V2TXLiveMixInputType) {
|
|
575
|
+
V2TXLiveMixInputType[V2TXLiveMixInputType["V2TXLiveMixInputTypeAudioVideo"] = 0] = "V2TXLiveMixInputTypeAudioVideo";
|
|
576
|
+
V2TXLiveMixInputType[V2TXLiveMixInputType["V2TXLiveMixInputTypePureVideo"] = 1] = "V2TXLiveMixInputTypePureVideo";
|
|
577
|
+
V2TXLiveMixInputType[V2TXLiveMixInputType["V2TXLiveMixInputTypePureAudio"] = 2] = "V2TXLiveMixInputTypePureAudio";
|
|
578
|
+
})(V2TXLiveMixInputType = exports.V2TXLiveMixInputType || (exports.V2TXLiveMixInputType = {}));
|
|
579
|
+
/**
|
|
580
|
+
* 云端混流中每一路子画面的位置信息
|
|
581
|
+
*
|
|
582
|
+
* @param {String} userId - 参与混流的 userId
|
|
583
|
+
* @param {String} streamId - 参与混流的 userId 所在对应的推流 streamId, 空的话表示当前推流 streamId。
|
|
584
|
+
* @param {Number} x - 图层位置 x 坐标(绝对像素值)。
|
|
585
|
+
* @param {Number} y - 图层位置 y 坐标(绝对像素值)。
|
|
586
|
+
* @param {Number} width - 图层位置宽度(绝对像素值)。
|
|
587
|
+
* @param {Number} height - 图层位置高度(绝对像素值)。
|
|
588
|
+
* @param {Number} zOrder - 图层层次(1 - 15)不可重复。
|
|
589
|
+
* @param {V2TXLiveMixInputType} inputType - 该直播流的输入类型。
|
|
590
|
+
*/
|
|
591
|
+
class V2TXLiveMixStream {
|
|
592
|
+
constructor(userId = '', streamId = '', x = 0, y = 0, width = 0, height = 0, zOrder = 0, inputType = V2TXLiveMixInputType.V2TXLiveMixInputTypeAudioVideo) {
|
|
593
|
+
this.userId = userId;
|
|
594
|
+
this.streamId = streamId;
|
|
595
|
+
this.x = x;
|
|
596
|
+
this.y = y;
|
|
597
|
+
this.width = width;
|
|
598
|
+
this.height = height;
|
|
599
|
+
this.zOrder = zOrder;
|
|
600
|
+
this.inputType = inputType;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
exports.V2TXLiveMixStream = V2TXLiveMixStream;
|
|
604
|
+
/**
|
|
605
|
+
* 云端混流(转码)配置
|
|
606
|
+
*
|
|
607
|
+
* @param {Number} videoWidth - 【字段含义】最终转码后的视频分辨率的宽度。<br>
|
|
608
|
+
* 【推荐取值】推荐值:360px ,如果你是纯音频推流,请将 width × height 设为 0px × 0px,否则混流后会携带一条画布背景的视频流。
|
|
609
|
+
* @param {Number} videoHeight - 【字段含义】最终转码后的视频分辨率的高度。<br>
|
|
610
|
+
* 【推荐取值】推荐值:640px ,如果你是纯音频推流,请将 width × height 设为 0px × 0px,否则混流后会携带一条画布背景的视频流。
|
|
611
|
+
* @param {Number} videoBitrate - 【字段含义】最终转码后的视频分辨率的码率(kbps)<br>
|
|
612
|
+
* 【推荐取值】如果填0,后台会根据videoWidth和videoHeight来估算码率,您也可以参考枚举定义TRTCVideoResolution_640_480的注释。
|
|
613
|
+
* @param {Number} videoFramerate - 【字段含义】最终转码后的视频分辨率的帧率(FPS)<br>
|
|
614
|
+
* 【推荐取值】默认值:15fps,取值范围是 (0,30]。
|
|
615
|
+
* @param {Number} videoGOP - 【字段含义】最终转码后的视频分辨率的关键帧间隔(又称为 GOP)。<br>
|
|
616
|
+
* 【推荐取值】默认值:2,单位为秒,取值范围是 [1,8]。
|
|
617
|
+
* @param {Number} backgroundColor - 【字段含义】混合后画面的底色颜色,默认为黑色,格式为十六进制数字,比如:“0x61B9F1” 代表 RGB 分别为(97,158,241)。<br>
|
|
618
|
+
* 【推荐取值】默认值:0x000000,黑色
|
|
619
|
+
* @param {String} backgroundImage - 【字段含义】混合后画面的背景图。<br>
|
|
620
|
+
* 【推荐取值】默认值:'',即不设置背景图<br>
|
|
621
|
+
* 【特别说明】背景图需要您事先在 “[控制台](https://console.cloud.tencent.com/trtc) => 应用管理 => 功能配置 => 素材管理” 中上传,<br>
|
|
622
|
+
* 上传成功后可以获得对应的“图片ID”,然后将“图片ID”转换成字符串类型并设置到 backgroundImage 里即可。<br>
|
|
623
|
+
* 例如:假设“图片ID” 为 63,可以设置 backgroundImage = @"63";
|
|
624
|
+
* @param {Number} audioSampleRate - 【字段含义】最终转码后的音频采样率。<br>
|
|
625
|
+
* 【推荐取值】默认值:48000Hz。支持12000HZ、16000HZ、22050HZ、24000HZ、32000HZ、44100HZ、48000HZ。
|
|
626
|
+
* @param {Number} audioBitrate - 【字段含义】最终转码后的音频码率。<br>
|
|
627
|
+
* 【推荐取值】默认值:64kbps,取值范围是 [32,192]。
|
|
628
|
+
* @param {Number} audioChannels - 【字段含义】最终转码后的音频声道数<br>
|
|
629
|
+
* 【推荐取值】默认值:1。取值范围为 [1,2] 中的整型。
|
|
630
|
+
* @param {V2TXLiveMixStream[]} mixStreams - 【字段含义】每一路子画面的位置信息
|
|
631
|
+
* @param {String} outputStreamId - 【字段含义】输出到 CDN 上的直播流 ID。<br>
|
|
632
|
+
* 如不设置该参数,SDK 会执行默认逻辑,即房间里的多路流会混合到该接口调用者的视频流上,也就是 A+B =>A;<br>
|
|
633
|
+
* 如果设置该参数,SDK 会将房间里的多路流混合到您指定的直播流 ID 上,也就是 A+B =>C。<br>
|
|
634
|
+
* 【推荐取值】默认值:'',即房间里的多路流会混合到该接口调用者的视频流上。
|
|
635
|
+
*/
|
|
636
|
+
class V2TXLiveTranscodingConfig {
|
|
637
|
+
constructor(videoWidth = 0, videoHeight = 0, videoBitrate = 0, videoFramerate = 15, videoGOP = 2, backgroundColor = 0, backgroundImage = '', audioSampleRate = 64, audioBitrate = 48000, audioChannels = 1, mixStreams = [], outputStreamId = '') {
|
|
638
|
+
this.videoWidth = videoWidth;
|
|
639
|
+
this.videoHeight = videoHeight;
|
|
640
|
+
this.videoBitrate = videoBitrate;
|
|
641
|
+
this.videoFramerate = videoFramerate;
|
|
642
|
+
this.videoGOP = videoGOP;
|
|
643
|
+
this.backgroundColor = backgroundColor;
|
|
644
|
+
this.backgroundImage = backgroundImage;
|
|
645
|
+
this.audioSampleRate = audioSampleRate;
|
|
646
|
+
this.audioBitrate = audioBitrate;
|
|
647
|
+
this.audioChannels = audioChannels;
|
|
648
|
+
this.mixStreams = mixStreams;
|
|
649
|
+
this.outputStreamId = outputStreamId;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
exports.V2TXLiveTranscodingConfig = V2TXLiveTranscodingConfig;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Rect, TRTCVideoFillMode } from "../trtc_define";
|
|
2
2
|
export declare type TRTCMediaInfo = {
|
|
3
3
|
id: string;
|
|
4
4
|
rect: Rect;
|
|
@@ -9,8 +9,6 @@ export declare type TRTCMediaInfo = {
|
|
|
9
9
|
declare class TRTCMediaMixingDesigner {
|
|
10
10
|
private logPrefix;
|
|
11
11
|
private container;
|
|
12
|
-
private videoResolution;
|
|
13
|
-
private resMode;
|
|
14
12
|
private mixingVideoWidth;
|
|
15
13
|
private mixingVideoHeight;
|
|
16
14
|
private canExceedContainer;
|
|
@@ -33,16 +31,20 @@ declare class TRTCMediaMixingDesigner {
|
|
|
33
31
|
private mousedownTop;
|
|
34
32
|
private eventButton;
|
|
35
33
|
private resizeObserver;
|
|
34
|
+
private relativeWorkingArea;
|
|
35
|
+
private absoluteWorkingArea;
|
|
36
|
+
private fillMode;
|
|
36
37
|
constructor(options: {
|
|
37
38
|
view: HTMLElement;
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
40
41
|
canExceedContainer: boolean;
|
|
41
42
|
});
|
|
42
43
|
updateOptions(options: {
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
45
46
|
}): void;
|
|
47
|
+
setWorkingArea(relative: Rect | null | undefined, fillMode?: TRTCVideoFillMode): void;
|
|
46
48
|
addMedia(media: TRTCMediaInfo): void;
|
|
47
49
|
removeMedia(media: TRTCMediaInfo): void;
|
|
48
50
|
updateMedia(media: TRTCMediaInfo): void;
|
|
@@ -54,6 +56,7 @@ declare class TRTCMediaMixingDesigner {
|
|
|
54
56
|
private initContainerMouseEventHander;
|
|
55
57
|
private initContainerResizeObserver;
|
|
56
58
|
private onPreviewAreaResize;
|
|
59
|
+
private updateWorkingArea;
|
|
57
60
|
private updatePreviewProperty;
|
|
58
61
|
private updateOverlay;
|
|
59
62
|
private onMove;
|
|
@@ -5,26 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const events_1 = require("events");
|
|
7
7
|
const trtc_define_1 = require("../trtc_define");
|
|
8
|
-
const utils_1 = require("../utils");
|
|
9
8
|
const logger_1 = __importDefault(require("../logger"));
|
|
10
9
|
const Movable_1 = __importDefault(require("./Movable"));
|
|
11
10
|
const Resizable_1 = __importDefault(require("./Resizable"));
|
|
12
11
|
const MIN_MOVE_DISTANCE = 5; // minimum moving distance
|
|
13
|
-
const initResolutionMap = () => {
|
|
14
|
-
const map = new Map();
|
|
15
|
-
for (const key in trtc_define_1.TRTCVideoResolution) {
|
|
16
|
-
if (isNaN(Number(key))) {
|
|
17
|
-
const value = trtc_define_1.TRTCVideoResolution[key];
|
|
18
|
-
const tmp = key.split('_');
|
|
19
|
-
map.set(value, {
|
|
20
|
-
width: parseInt(tmp[1]),
|
|
21
|
-
height: parseInt(tmp[2]),
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return map;
|
|
26
|
-
};
|
|
27
|
-
const resolutionMap = initResolutionMap();
|
|
28
12
|
class TRTCMediaMixingDesigner {
|
|
29
13
|
constructor(options) {
|
|
30
14
|
this.logPrefix = '[TRTCMediaMixingDesigner]';
|
|
@@ -48,19 +32,12 @@ class TRTCMediaMixingDesigner {
|
|
|
48
32
|
this.resizeObserver = null;
|
|
49
33
|
this.container = options.view;
|
|
50
34
|
this.container.style.position = 'absolute';
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.mixingVideoHeight = height;
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
this.mixingVideoWidth = height;
|
|
61
|
-
this.mixingVideoHeight = width;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
35
|
+
this.relativeWorkingArea = { left: 0, top: 0, right: 1, bottom: 1 };
|
|
36
|
+
this.absoluteWorkingArea = {};
|
|
37
|
+
this.fillMode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit;
|
|
38
|
+
this.updateWorkingArea();
|
|
39
|
+
this.mixingVideoWidth = options.width;
|
|
40
|
+
this.mixingVideoHeight = options.height;
|
|
64
41
|
this.updatePreviewProperty();
|
|
65
42
|
this.canExceedContainer = options.canExceedContainer || false;
|
|
66
43
|
this.eventEmitter = new events_1.EventEmitter();
|
|
@@ -75,24 +52,25 @@ class TRTCMediaMixingDesigner {
|
|
|
75
52
|
this.initContainerResizeObserver();
|
|
76
53
|
}
|
|
77
54
|
updateOptions(options) {
|
|
78
|
-
if (
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
}
|
|
55
|
+
if (this.mixingVideoWidth !== options.width || this.mixingVideoHeight !== options.height) {
|
|
56
|
+
this.mixingVideoWidth = options.width;
|
|
57
|
+
this.mixingVideoHeight = options.height;
|
|
58
|
+
this.updatePreviewProperty();
|
|
59
|
+
this.updateOverlay();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
setWorkingArea(relative, fillMode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit) {
|
|
63
|
+
logger_1.default.log(`${this.logPrefix}setWorkingArea:`, JSON.stringify(relative), `fillMode:${fillMode}`);
|
|
64
|
+
if (relative) {
|
|
65
|
+
this.relativeWorkingArea = Object.assign({}, relative);
|
|
66
|
+
this.fillMode = fillMode;
|
|
67
|
+
this.updateWorkingArea();
|
|
93
68
|
this.updatePreviewProperty();
|
|
94
69
|
this.updateOverlay();
|
|
95
70
|
}
|
|
71
|
+
else {
|
|
72
|
+
logger_1.default.error(`${this.logPrefix}setWorkingArea invalid parameter:`, relative);
|
|
73
|
+
}
|
|
96
74
|
}
|
|
97
75
|
addMedia(media) {
|
|
98
76
|
this.mediaList.unshift(media);
|
|
@@ -194,50 +172,98 @@ class TRTCMediaMixingDesigner {
|
|
|
194
172
|
logger_1.default.log(`${this.logPrefix}onPreviewAreaResize:`, entries);
|
|
195
173
|
for (const entry of entries) {
|
|
196
174
|
if (entry.target === this.container) {
|
|
175
|
+
this.updateWorkingArea();
|
|
197
176
|
this.updatePreviewProperty();
|
|
198
177
|
this.updateOverlay();
|
|
199
178
|
break;
|
|
200
179
|
}
|
|
201
180
|
}
|
|
202
181
|
}
|
|
182
|
+
updateWorkingArea() {
|
|
183
|
+
if (this.relativeWorkingArea && this.container) {
|
|
184
|
+
const containerRect = this.container.getBoundingClientRect();
|
|
185
|
+
this.absoluteWorkingArea = {
|
|
186
|
+
left: this.relativeWorkingArea.left * containerRect.width,
|
|
187
|
+
top: this.relativeWorkingArea.top * containerRect.height,
|
|
188
|
+
right: this.relativeWorkingArea.right * containerRect.width,
|
|
189
|
+
bottom: this.relativeWorkingArea.bottom * containerRect.height,
|
|
190
|
+
width: (this.relativeWorkingArea.right - this.relativeWorkingArea.left) * containerRect.width,
|
|
191
|
+
height: (this.relativeWorkingArea.bottom - this.relativeWorkingArea.top) * containerRect.height,
|
|
192
|
+
};
|
|
193
|
+
logger_1.default.log(`${this.logPrefix}updateWorkingArea absolute working area:`, JSON.stringify(this.absoluteWorkingArea));
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
logger_1.default.error(`${this.logPrefix}updateWorkingArea no data:`, this.relativeWorkingArea, this.container);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
203
199
|
updatePreviewProperty() {
|
|
204
|
-
if (this.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
200
|
+
if (this.absoluteWorkingArea) {
|
|
201
|
+
if (this.mixingVideoWidth <= 0 || this.mixingVideoHeight <= 0) {
|
|
202
|
+
logger_1.default.error(`${this.logPrefix}updatePreviewProperty failed, mixingVideoWidth or mixingVideoHeight is zero`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const workingAreaWidth = this.absoluteWorkingArea.width;
|
|
206
|
+
const workingAreaHeight = this.absoluteWorkingArea.height;
|
|
207
|
+
const widthScale = workingAreaWidth / this.mixingVideoWidth;
|
|
208
|
+
const heightScale = workingAreaHeight / this.mixingVideoHeight;
|
|
209
|
+
if (this.fillMode === trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fill) {
|
|
210
|
+
this.previewScale = widthScale > heightScale ? widthScale : heightScale;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.fillMode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit;
|
|
214
|
+
this.previewScale = widthScale > heightScale ? heightScale : widthScale;
|
|
215
|
+
}
|
|
210
216
|
this.previewWidth = this.mixingVideoWidth * this.previewScale;
|
|
211
217
|
this.previewHeight = this.mixingVideoHeight * this.previewScale;
|
|
212
|
-
this.previewLeft = (
|
|
213
|
-
this.previewTop = (
|
|
218
|
+
this.previewLeft = (workingAreaWidth - this.previewWidth) / 2;
|
|
219
|
+
this.previewTop = (workingAreaHeight - this.previewHeight) / 2;
|
|
220
|
+
logger_1.default.debug(`${this.logPrefix}updatePreviewProperty: fillMode: ${this.fillMode} previewScale: ${this.previewScale}, previewWidth: ${this.previewWidth}, previewHeight: ${this.previewHeight}, previewLeft: ${this.previewLeft}, previewTop: ${this.previewTop}`);
|
|
214
221
|
}
|
|
215
222
|
else {
|
|
216
|
-
logger_1.default.error(`${this.logPrefix}
|
|
223
|
+
logger_1.default.error(`${this.logPrefix}updatePreviewProperty failed, no HTML element to display`);
|
|
217
224
|
}
|
|
218
225
|
}
|
|
219
226
|
updateOverlay() {
|
|
220
227
|
if (this.moveAndResizeOverlay) {
|
|
221
|
-
let left =
|
|
222
|
-
let top =
|
|
223
|
-
let width =
|
|
224
|
-
let height =
|
|
228
|
+
let left = this.absoluteWorkingArea.left + this.previewLeft;
|
|
229
|
+
let top = this.absoluteWorkingArea.top + this.previewTop;
|
|
230
|
+
let width = 0;
|
|
231
|
+
let height = 0;
|
|
225
232
|
if (this.selectedMediaIndex >= 0) {
|
|
233
|
+
logger_1.default.debug(`${this.logPrefix}updateOverlay: selected media:`, this.mediaList[this.selectedMediaIndex].rect);
|
|
226
234
|
const selectedPreviewRect = {
|
|
227
235
|
left: this.mediaList[this.selectedMediaIndex].rect.left * this.previewScale,
|
|
228
236
|
top: this.mediaList[this.selectedMediaIndex].rect.top * this.previewScale,
|
|
229
237
|
right: this.mediaList[this.selectedMediaIndex].rect.right * this.previewScale,
|
|
230
238
|
bottom: this.mediaList[this.selectedMediaIndex].rect.bottom * this.previewScale
|
|
231
239
|
};
|
|
232
|
-
left =
|
|
233
|
-
top =
|
|
234
|
-
width =
|
|
235
|
-
height =
|
|
240
|
+
left = this.absoluteWorkingArea.left + this.previewLeft + selectedPreviewRect.left;
|
|
241
|
+
top = this.absoluteWorkingArea.top + this.previewTop + selectedPreviewRect.top;
|
|
242
|
+
width = selectedPreviewRect.right - selectedPreviewRect.left;
|
|
243
|
+
height = selectedPreviewRect.bottom - selectedPreviewRect.top;
|
|
244
|
+
}
|
|
245
|
+
let renderScale = 1;
|
|
246
|
+
if (this.container) {
|
|
247
|
+
const containerLayoutWidth = this.container.offsetWidth;
|
|
248
|
+
const containerRenderWidth = Math.round(this.container.getBoundingClientRect().width);
|
|
249
|
+
if (containerLayoutWidth !== containerRenderWidth) {
|
|
250
|
+
logger_1.default.warn(`${this.logPrefix}updateOverlay container layout width: ${containerLayoutWidth} container render width: ${containerRenderWidth}`);
|
|
251
|
+
renderScale = containerRenderWidth / containerLayoutWidth;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
this.moveAndResizeOverlay.style.left = `${left}px`;
|
|
255
|
+
this.moveAndResizeOverlay.style.top = `${top}px`;
|
|
256
|
+
this.moveAndResizeOverlay.style.width = `${width}px`;
|
|
257
|
+
this.moveAndResizeOverlay.style.height = `${height}px`;
|
|
258
|
+
if (renderScale !== 1) {
|
|
259
|
+
this.moveAndResizeOverlay.style.transform = `scale(${1 / renderScale})`;
|
|
260
|
+
this.moveAndResizeOverlay.style.transformOrigin = `-${left}px -${top}px`; // Why?
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
this.moveAndResizeOverlay.style.transform = 'none';
|
|
264
|
+
this.moveAndResizeOverlay.style.transformOrigin = 'none';
|
|
236
265
|
}
|
|
237
|
-
|
|
238
|
-
this.moveAndResizeOverlay.style.top = top;
|
|
239
|
-
this.moveAndResizeOverlay.style.width = width;
|
|
240
|
-
this.moveAndResizeOverlay.style.height = height;
|
|
266
|
+
logger_1.default.debug(`${this.logPrefix}updateOverlay: ${left} ${top} ${width} ${height} ${renderScale}`);
|
|
241
267
|
}
|
|
242
268
|
}
|
|
243
269
|
onMove(left, top) {
|
|
@@ -247,10 +273,10 @@ class TRTCMediaMixingDesigner {
|
|
|
247
273
|
if (target && this.moveAndResizeOverlay) {
|
|
248
274
|
// calc new preview rect
|
|
249
275
|
const newPreviewRect = {
|
|
250
|
-
left: left - this.previewLeft,
|
|
251
|
-
top: top - this.previewTop,
|
|
252
|
-
right: left - this.previewLeft + this.moveAndResizeOverlay.offsetWidth,
|
|
253
|
-
bottom: top - this.previewTop + this.moveAndResizeOverlay.offsetHeight,
|
|
276
|
+
left: left - this.absoluteWorkingArea.left - this.previewLeft,
|
|
277
|
+
top: top - this.absoluteWorkingArea.top - this.previewTop,
|
|
278
|
+
right: left - this.absoluteWorkingArea.left - this.previewLeft + this.moveAndResizeOverlay.offsetWidth,
|
|
279
|
+
bottom: top - this.absoluteWorkingArea.top - this.previewTop + this.moveAndResizeOverlay.offsetHeight,
|
|
254
280
|
};
|
|
255
281
|
this.doAdsorption(newPreviewRect);
|
|
256
282
|
// calc new mixing rect
|
|
@@ -260,6 +286,8 @@ class TRTCMediaMixingDesigner {
|
|
|
260
286
|
right: Math.round(newPreviewRect.right / this.previewScale),
|
|
261
287
|
bottom: Math.round(newPreviewRect.bottom / this.previewScale),
|
|
262
288
|
};
|
|
289
|
+
logger_1.default.debug(`${this.logPrefix}onMove new preview rect: ${JSON.stringify(newPreviewRect)}`);
|
|
290
|
+
logger_1.default.debug(`${this.logPrefix}onMove new rect in mixing: ${JSON.stringify(newRectInMixing)}`);
|
|
263
291
|
(_a = this.eventEmitter) === null || _a === void 0 ? void 0 : _a.emit('onSourceMoved', Object.assign({}, target), newRectInMixing);
|
|
264
292
|
}
|
|
265
293
|
else {
|
|
@@ -292,10 +320,10 @@ class TRTCMediaMixingDesigner {
|
|
|
292
320
|
if (target) {
|
|
293
321
|
// calc new preview rect
|
|
294
322
|
const newPreviewRect = {
|
|
295
|
-
left: left - this.previewLeft,
|
|
296
|
-
top: top - this.previewTop,
|
|
297
|
-
right: left - this.previewLeft + width,
|
|
298
|
-
bottom: top - this.previewTop + height,
|
|
323
|
+
left: left - this.absoluteWorkingArea.left - this.previewLeft,
|
|
324
|
+
top: top - this.absoluteWorkingArea.top - this.previewTop,
|
|
325
|
+
right: left - this.absoluteWorkingArea.left - this.previewLeft + width,
|
|
326
|
+
bottom: top - this.absoluteWorkingArea.top - this.previewTop + height,
|
|
299
327
|
};
|
|
300
328
|
// calc new mixing rect
|
|
301
329
|
const newRectInMixing = {
|
|
@@ -335,8 +363,8 @@ class TRTCMediaMixingDesigner {
|
|
|
335
363
|
// calc click point coordinates in mix video image
|
|
336
364
|
logger_1.default.log(`${this.logPrefix}onContainerMousedown mix video image clicked`);
|
|
337
365
|
const containerBounds = this.container.getBoundingClientRect();
|
|
338
|
-
const xInPreviewImage = event.clientX - containerBounds.
|
|
339
|
-
const yInPreviewImage = event.clientY - containerBounds.
|
|
366
|
+
const xInPreviewImage = event.clientX - containerBounds.left - this.absoluteWorkingArea.left - this.previewLeft;
|
|
367
|
+
const yInPreviewImage = event.clientY - containerBounds.top - this.absoluteWorkingArea.top - this.previewTop;
|
|
340
368
|
const xInImage = xInPreviewImage / this.previewScale;
|
|
341
369
|
const yInImage = yInPreviewImage / this.previewScale;
|
|
342
370
|
logger_1.default.log(`${this.logPrefix}onContainerMousedown click point coordinates in mix video:`, xInPreviewImage, yInPreviewImage, xInImage, yInImage);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const LOCAL_USER_ID = "";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TRTCStreamLayout, TRTCStreamLayoutMode } from "../types";
|
|
2
|
+
import { ITRTCStreamLayoutManager, INativeStreamLayoutManager, TRTCStreamLayoutContext } from "./types";
|
|
3
|
+
declare class BaseStreamLayoutManager implements ITRTCStreamLayoutManager {
|
|
4
|
+
protected logPrefix: string;
|
|
5
|
+
protected nativeStreamLayoutManager: INativeStreamLayoutManager;
|
|
6
|
+
protected layout: TRTCStreamLayout;
|
|
7
|
+
protected context: TRTCStreamLayoutContext | null;
|
|
8
|
+
protected container: HTMLElement | null;
|
|
9
|
+
protected displayArea: {
|
|
10
|
+
left: number;
|
|
11
|
+
top: number;
|
|
12
|
+
right: number;
|
|
13
|
+
bottom: number;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
};
|
|
17
|
+
protected resizeObserver: ResizeObserver | null;
|
|
18
|
+
constructor(nativeStreamLayoutManager: INativeStreamLayoutManager, context: TRTCStreamLayoutContext);
|
|
19
|
+
setLayout(layout: TRTCStreamLayout): void;
|
|
20
|
+
getLayoutMode(): TRTCStreamLayoutMode;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
protected refreshLayout(): void;
|
|
23
|
+
private onResize;
|
|
24
|
+
private setResizeObserver;
|
|
25
|
+
private updateDisplayArea;
|
|
26
|
+
}
|
|
27
|
+
export default BaseStreamLayoutManager;
|