trtc-electron-sdk 13.3.800-alpha.1 → 13.3.800-alpha.2
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/README.md +5 -5
- package/liteav/index.d.ts +1 -0
- package/liteav/index.js +3 -0
- package/liteav/types.d.ts +46 -1
- package/liteav/types.js +11 -0
- package/liteav/vod_player.d.ts +97 -49
- package/liteav/vod_player.js +226 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ Tencent Real-Time Communication (TRTC) is a set of low-latency, high-quality rea
|
|
|
11
11
|
- ⬆️ [Publishing to CSS CDN](https://www.tencentcloud.com/document/product/647/47858#)
|
|
12
12
|
|
|
13
13
|
## 💻 Environment Support
|
|
14
|
-
- 🍎
|
|
15
|
-
-
|
|
14
|
+
- 🍎 macOS **11.0 (Big Sur)** and above, x64 and arm64 (**Electron 11+**)
|
|
15
|
+
- 🪟 Windows 7 SP1 and above, ia32 and x64
|
|
16
16
|
- 🌈 Electron: 8.5.0 and above
|
|
17
17
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
| x64 \| arm64
|
|
18
|
+
| macOS | Windows | Electron |
|
|
19
|
+
| :--------------------: | :---------: | :------------: |
|
|
20
|
+
| 11.0+ (x64 \| arm64) | ia32 \| x64 | 8.5.0 and above |
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
## ⏬ Install
|
package/liteav/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './trtc_define';
|
|
2
2
|
export * from './trtc_code';
|
|
3
3
|
export * from './vod_player';
|
|
4
|
+
export { VodPlayerEvents, VodPlayerEventMap, IVodPlayer } from './types';
|
|
4
5
|
export * from './extensions/DeviceManager';
|
|
5
6
|
export * from './extensions/AudioEffectManager';
|
|
6
7
|
export * from './extensions/MediaMixingManager';
|
package/liteav/index.js
CHANGED
|
@@ -13,9 +13,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.VodPlayerEvents = void 0;
|
|
16
17
|
__exportStar(require("./trtc_define"), exports);
|
|
17
18
|
__exportStar(require("./trtc_code"), exports);
|
|
18
19
|
__exportStar(require("./vod_player"), exports);
|
|
20
|
+
var types_1 = require("./types");
|
|
21
|
+
Object.defineProperty(exports, "VodPlayerEvents", { enumerable: true, get: function () { return types_1.VodPlayerEvents; } });
|
|
19
22
|
__exportStar(require("./extensions/DeviceManager"), exports);
|
|
20
23
|
__exportStar(require("./extensions/AudioEffectManager"), exports);
|
|
21
24
|
__exportStar(require("./extensions/MediaMixingManager"), exports);
|
package/liteav/types.d.ts
CHANGED
|
@@ -1,8 +1,53 @@
|
|
|
1
1
|
import TRTCMediaMixingManager, { TRTCMediaMixingService } from './extensions/MediaMixingManager';
|
|
2
|
-
import { AudioMusicParam, Rect, TRTCAppScene, TRTCAudioQuality, TRTCBeautyStyle, TRTCDeviceType, TRTCLogLevel, TRTCAudioFrame, TRTCVideoRotation, TRTCVideoStreamType, TRTCWaterMarkSrcType, TRTCPluginType, TRTCPluginInfo, TRTCVideoProcessPluginOptions, TRTCMediaEncryptDecryptPluginOptions, TRTCAudioRecordingParams, TRTCScreenCaptureSourceInfo, TRTCScreenCaptureProperty, TRTCSpeedTestParams, TRTCRecordType, TRTCDeviceInfo, TRTCCameraCaptureParams, TRTCImageBuffer, TRTCInitConfig, TRTCAudioParallelParams, TRTCVoiceReverbType, TRTCVoiceChangerType, TRTCMusicPlayObserver, TRTCAudioFrameCallback, TRTCAudioProcessPluginOptions, TRTCPublishTarget, TRTCStreamEncoderParam, TRTCStreamMixingConfig, TRTCRenderParams, TRTCRoleType, TRTCSwitchRoomParam, TRTCVideoFrame, TRTCVideoPixelFormat, TRTCVideoBufferType } from './trtc_define';
|
|
2
|
+
import { AudioMusicParam, Rect, TRTCAppScene, TRTCAudioQuality, TRTCBeautyStyle, TRTCDeviceType, TRTCLogLevel, TRTCAudioFrame, TRTCVideoFillMode, TRTCVideoRotation, TRTCVideoStreamType, TRTCWaterMarkSrcType, TRTCPluginType, TRTCPluginInfo, TRTCVideoProcessPluginOptions, TRTCMediaEncryptDecryptPluginOptions, TRTCAudioRecordingParams, TRTCScreenCaptureSourceInfo, TRTCScreenCaptureProperty, TRTCSpeedTestParams, TRTCRecordType, TRTCDeviceInfo, TRTCCameraCaptureParams, TRTCImageBuffer, TRTCInitConfig, TRTCAudioParallelParams, TRTCVoiceReverbType, TRTCVoiceChangerType, TRTCMusicPlayObserver, TRTCAudioFrameCallback, TRTCAudioProcessPluginOptions, TRTCPublishTarget, TRTCStreamEncoderParam, TRTCStreamMixingConfig, TRTCRenderParams, TRTCRoleType, TRTCSwitchRoomParam, TRTCVideoFrame, TRTCVideoPixelFormat, TRTCVideoBufferType } from './trtc_define';
|
|
3
3
|
export interface TRTCVideoRenderCallback {
|
|
4
4
|
onRenderVideoFrame(userId: string, streamType: TRTCVideoStreamType, frame: TRTCVideoFrame): void;
|
|
5
5
|
}
|
|
6
|
+
export declare enum VodPlayerEvents {
|
|
7
|
+
onVodPlayerStarted = "onVodPlayerStarted",
|
|
8
|
+
onVodPlayerLoaded = "onVodPlayerLoaded",
|
|
9
|
+
onVodPlayerProgress = "onVodPlayerProgress",
|
|
10
|
+
onVodPlayerPaused = "onVodPlayerPaused",
|
|
11
|
+
onVodPlayerResumed = "onVodPlayerResumed",
|
|
12
|
+
onVodPlayerStopped = "onVodPlayerStopped",
|
|
13
|
+
onVodPlayerError = "onVodPlayerError"
|
|
14
|
+
}
|
|
15
|
+
export interface VodPlayerEventMap {
|
|
16
|
+
[VodPlayerEvents.onVodPlayerStarted]: [msLength: number];
|
|
17
|
+
[VodPlayerEvents.onVodPlayerLoaded]: [durationMs: number, width: number, height: number];
|
|
18
|
+
[VodPlayerEvents.onVodPlayerProgress]: [msPos: number];
|
|
19
|
+
[VodPlayerEvents.onVodPlayerPaused]: [];
|
|
20
|
+
[VodPlayerEvents.onVodPlayerResumed]: [];
|
|
21
|
+
[VodPlayerEvents.onVodPlayerStopped]: [reason: number];
|
|
22
|
+
[VodPlayerEvents.onVodPlayerError]: [error: number];
|
|
23
|
+
}
|
|
24
|
+
export interface IVodPlayer {
|
|
25
|
+
on<K extends keyof VodPlayerEventMap>(event: K, listener: (...args: VodPlayerEventMap[K]) => void): this;
|
|
26
|
+
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
27
|
+
off<K extends keyof VodPlayerEventMap>(event: K, listener: (...args: VodPlayerEventMap[K]) => void): this;
|
|
28
|
+
off(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
29
|
+
setView(view: HTMLElement | null): void;
|
|
30
|
+
setRenderRotation(rotation: TRTCVideoRotation): void;
|
|
31
|
+
setFillMode(mode: TRTCVideoFillMode): void;
|
|
32
|
+
setMirror(mirror: boolean): void;
|
|
33
|
+
preload(): void;
|
|
34
|
+
start(): void;
|
|
35
|
+
pause(): void;
|
|
36
|
+
resume(): void;
|
|
37
|
+
seek(msPos: number): void;
|
|
38
|
+
switchSource(newMediaFile: string): void;
|
|
39
|
+
stop(): void;
|
|
40
|
+
getDuration(): number;
|
|
41
|
+
getWidth(): number;
|
|
42
|
+
getHeight(): number;
|
|
43
|
+
mute(mute: boolean): void;
|
|
44
|
+
setVolume(volume: number): void;
|
|
45
|
+
publishVideo(): void;
|
|
46
|
+
publishAudio(): void;
|
|
47
|
+
unpublishVideo(): void;
|
|
48
|
+
unpublishAudio(): void;
|
|
49
|
+
destroy(): void;
|
|
50
|
+
}
|
|
6
51
|
export interface ITRTCCloud {
|
|
7
52
|
createSubCloud(config?: TRTCInitConfig): ITRTCCloud | null;
|
|
8
53
|
enterRoom(params: any, scene: TRTCAppScene): void;
|
package/liteav/types.js
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VodPlayerEvents = void 0;
|
|
4
|
+
var VodPlayerEvents;
|
|
5
|
+
(function (VodPlayerEvents) {
|
|
6
|
+
VodPlayerEvents["onVodPlayerStarted"] = "onVodPlayerStarted";
|
|
7
|
+
VodPlayerEvents["onVodPlayerLoaded"] = "onVodPlayerLoaded";
|
|
8
|
+
VodPlayerEvents["onVodPlayerProgress"] = "onVodPlayerProgress";
|
|
9
|
+
VodPlayerEvents["onVodPlayerPaused"] = "onVodPlayerPaused";
|
|
10
|
+
VodPlayerEvents["onVodPlayerResumed"] = "onVodPlayerResumed";
|
|
11
|
+
VodPlayerEvents["onVodPlayerStopped"] = "onVodPlayerStopped";
|
|
12
|
+
VodPlayerEvents["onVodPlayerError"] = "onVodPlayerError";
|
|
13
|
+
})(VodPlayerEvents = exports.VodPlayerEvents || (exports.VodPlayerEvents = {}));
|
package/liteav/vod_player.d.ts
CHANGED
|
@@ -1,34 +1,5 @@
|
|
|
1
1
|
import { TRTCVideoRotation, TRTCVideoFillMode } from './trtc_define';
|
|
2
|
-
|
|
3
|
-
* VodPlayer 播放器事件枚举
|
|
4
|
-
*/
|
|
5
|
-
export declare enum VodPlayerEvents {
|
|
6
|
-
/** 播放开始,参数:msLength(总时长,毫秒) */
|
|
7
|
-
onVodPlayerStarted = "onVodPlayerStarted",
|
|
8
|
-
/** 播放进度更新,参数:msPos(当前进度,毫秒) */
|
|
9
|
-
onVodPlayerProgress = "onVodPlayerProgress",
|
|
10
|
-
/** 播放暂停 */
|
|
11
|
-
onVodPlayerPaused = "onVodPlayerPaused",
|
|
12
|
-
/** 播放恢复 */
|
|
13
|
-
onVodPlayerResumed = "onVodPlayerResumed",
|
|
14
|
-
/** 播放停止,参数:reason(0=用户主动停止,1=文件播放完,2=视频断流) */
|
|
15
|
-
onVodPlayerStopped = "onVodPlayerStopped",
|
|
16
|
-
/** 播放错误,参数:error(错误码) */
|
|
17
|
-
onVodPlayerError = "onVodPlayerError"
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* VodPlayer 事件与回调参数的类型映射
|
|
21
|
-
*
|
|
22
|
-
* 用于 on/off 方法的类型约束,使事件名和回调参数在编译期匹配。
|
|
23
|
-
*/
|
|
24
|
-
export interface VodPlayerEventMap {
|
|
25
|
-
[VodPlayerEvents.onVodPlayerStarted]: [msLength: number];
|
|
26
|
-
[VodPlayerEvents.onVodPlayerProgress]: [msPos: number];
|
|
27
|
-
[VodPlayerEvents.onVodPlayerPaused]: [];
|
|
28
|
-
[VodPlayerEvents.onVodPlayerResumed]: [];
|
|
29
|
-
[VodPlayerEvents.onVodPlayerStopped]: [reason: number];
|
|
30
|
-
[VodPlayerEvents.onVodPlayerError]: [error: number];
|
|
31
|
-
}
|
|
2
|
+
import { IVodPlayer, VodPlayerEventMap } from './types';
|
|
32
3
|
/**
|
|
33
4
|
*
|
|
34
5
|
* 腾讯云点播播放器
|
|
@@ -51,21 +22,29 @@ export interface VodPlayerEventMap {
|
|
|
51
22
|
* // 使用完毕后销毁
|
|
52
23
|
* VodPlayer.releaseVodPlayer(player);
|
|
53
24
|
*/
|
|
54
|
-
export declare class VodPlayer {
|
|
25
|
+
export declare class VodPlayer implements IVodPlayer {
|
|
26
|
+
/** `_dataRenderCallback` 中允许连续重置 video buffer 的最大次数,超过后退化为周期日志 */
|
|
27
|
+
private static readonly MAX_BUFFER_RETRY;
|
|
28
|
+
/** 重试上限达到后,每隔多少帧打一次 warn 日志(按 30fps 估算 ≈ 2 秒一次) */
|
|
29
|
+
private static readonly BUFFER_RETRY_LOG_INTERVAL;
|
|
55
30
|
private nativeVodPlayer;
|
|
56
31
|
private videoRender;
|
|
57
32
|
private mediaFilePath;
|
|
58
|
-
private repeat;
|
|
59
33
|
private isStarted;
|
|
60
34
|
private isDestroyed;
|
|
35
|
+
private isRenderPrepared;
|
|
36
|
+
/** 数据回调中连续 setVideoBuffer 失败次数(用于 _dataRenderCallback 退避策略) */
|
|
37
|
+
private _setBufferRetryCount;
|
|
61
38
|
private logger;
|
|
62
39
|
private eventEmitter;
|
|
63
40
|
/**
|
|
64
41
|
* 创建 VodPlayer 实例
|
|
65
42
|
*
|
|
66
|
-
* @param mediaFilePath -
|
|
43
|
+
* @param mediaFilePath - 媒体文件路径(本地绝对路径或在线 URL),必填且必须是非空字符串
|
|
67
44
|
* @param repeat - 是否循环播放,默认 false
|
|
68
45
|
* @returns VodPlayer 实例
|
|
46
|
+
*
|
|
47
|
+
* @throws {TypeError} 当 `mediaFilePath` 不是非空字符串时抛出
|
|
69
48
|
*/
|
|
70
49
|
static createVodPlayer(mediaFilePath: string, repeat?: boolean): VodPlayer;
|
|
71
50
|
/**
|
|
@@ -100,61 +79,120 @@ export declare class VodPlayer {
|
|
|
100
79
|
/**
|
|
101
80
|
* 设置视频渲染的 DOM 容器
|
|
102
81
|
*
|
|
103
|
-
* @param view - HTML
|
|
82
|
+
* @param view - HTML 元素,用于承载视频画面;传 `null` 时仅解除当前 view 关联,
|
|
83
|
+
* 播放/渲染管线不受影响(可后续再次 `setView(newDom)` 切换容器)。
|
|
84
|
+
*
|
|
85
|
+
* @note 若调用方需要彻底停止渲染,请使用 {@link stop} 或 {@link destroy}。
|
|
104
86
|
*/
|
|
105
87
|
setView(view: HTMLElement | null): void;
|
|
88
|
+
/**
|
|
89
|
+
* 预加载多媒体文件
|
|
90
|
+
*
|
|
91
|
+
* 预加载完成后会触发 {@link VodPlayerEvents.onVodPlayerLoaded} 事件,事件参数携带
|
|
92
|
+
* 媒体信息(时长、宽高);同时 C++ 层会产生首帧并推送到 JS 层的视频渲染管线,
|
|
93
|
+
* 在 view 上展示首帧画面。
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* player.on(VodPlayerEvents.onVodPlayerLoaded, (durationMs, width, height) => {
|
|
97
|
+
* console.log('预加载完成:', durationMs, width, height);
|
|
98
|
+
* player.start();
|
|
99
|
+
* });
|
|
100
|
+
* player.preload();
|
|
101
|
+
*
|
|
102
|
+
* @note 可以先调用 preload 再调用 {@link start} 播放,也可以不调用 preload 直接调用 {@link start}。
|
|
103
|
+
* @note 若已经调用过 {@link start},再调用 preload 将无效。
|
|
104
|
+
*/
|
|
105
|
+
preload(): void;
|
|
106
106
|
/**
|
|
107
107
|
* 开始播放
|
|
108
108
|
*
|
|
109
|
+
* 支持的视频格式:mp4、mkv、mov。
|
|
110
|
+
* 支持的音频格式:opus、aac。
|
|
111
|
+
*
|
|
112
|
+
* 重复调用会被忽略。
|
|
113
|
+
*
|
|
114
|
+
* @note 可以先调用 {@link preload} 预加载完成后再调用 start,也可以跳过 preload 直接调用 start。
|
|
115
|
+
* @note 从 SDK 10.7 版本开始,需要通过 TXLiveBase#setLicence 设置 Licence 后方可成功播放,
|
|
116
|
+
* 否则将播放失败(黑屏),全局仅设置一次即可。
|
|
109
117
|
*/
|
|
110
118
|
start(): void;
|
|
111
119
|
/**
|
|
112
120
|
* 停止播放
|
|
113
|
-
*
|
|
114
121
|
*/
|
|
115
122
|
stop(): void;
|
|
116
123
|
/**
|
|
117
124
|
* 暂停播放
|
|
125
|
+
*
|
|
126
|
+
* @note 仅在 {@link start} 之后调用才有效;未播放时调用会被忽略并打 warn 日志。
|
|
118
127
|
*/
|
|
119
128
|
pause(): void;
|
|
120
129
|
/**
|
|
121
130
|
* 恢复播放
|
|
131
|
+
*
|
|
132
|
+
* @note 仅在 {@link start} 之后调用才有效;未播放时调用会被忽略并打 warn 日志。
|
|
122
133
|
*/
|
|
123
134
|
resume(): void;
|
|
124
135
|
/**
|
|
125
|
-
*
|
|
136
|
+
* 跳转到指定播放位置(seek)
|
|
126
137
|
*
|
|
127
138
|
* @param msPos - 目标位置,单位毫秒
|
|
139
|
+
*
|
|
140
|
+
* @note 调用前必须先 {@link preload} 或 {@link start},否则会被忽略并打 warn 日志。
|
|
128
141
|
*/
|
|
129
142
|
seek(msPos: number): void;
|
|
130
143
|
/**
|
|
131
|
-
*
|
|
144
|
+
* 无缝切换当前播放的媒体文件
|
|
145
|
+
*
|
|
146
|
+
* 在后台预加载新的媒体源,待新源就绪后无缝切换,避免切换时出现黑屏。
|
|
147
|
+
* 切换成功后触发 {@link VodPlayerEvents.onVodPlayerLoaded} 事件,携带新文件的媒体信息。
|
|
148
|
+
*
|
|
149
|
+
* @param newMediaFile - 新的媒体文件路径或 URL
|
|
150
|
+
*
|
|
151
|
+
* @note 若当前处于暂停状态,切换后仍保持暂停并展示新文件第一帧。
|
|
152
|
+
* @note 切换过程中调用 {@link stop} 会取消切换并停止当前播放。
|
|
153
|
+
* @note 调用前必须先 {@link preload} 或 {@link start},否则会被忽略并打 warn 日志。
|
|
154
|
+
* @note 传入空串会被忽略并打 warn 日志(C++ 层亦有同等保护)。
|
|
155
|
+
*/
|
|
156
|
+
switchSource(newMediaFile: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* 获取视频总时长
|
|
159
|
+
*
|
|
160
|
+
* @returns 总时长,单位毫秒;播放器已销毁时返回 0。
|
|
132
161
|
*
|
|
133
|
-
* @
|
|
162
|
+
* @note 跨平台口径已统一为 `int64_t`(即使 Windows x64 下底层 `long` 是 32 位,
|
|
163
|
+
* binding 层也会显式扩到 64 位避免 ~49 天回绕);JS `number` 安全整数上限 2^53,
|
|
164
|
+
* 业务上点播时长不会触及。
|
|
134
165
|
*/
|
|
135
166
|
getDuration(): number;
|
|
136
167
|
/**
|
|
137
168
|
* 获取视频宽度
|
|
138
169
|
*
|
|
139
|
-
* @returns
|
|
170
|
+
* @returns 视频宽度(像素);纯音频文件或播放器已销毁时返回 0
|
|
140
171
|
*/
|
|
141
172
|
getWidth(): number;
|
|
142
173
|
/**
|
|
143
174
|
* 获取视频高度
|
|
144
175
|
*
|
|
145
|
-
* @returns
|
|
176
|
+
* @returns 视频高度(像素);纯音频文件或播放器已销毁时返回 0
|
|
146
177
|
*/
|
|
147
178
|
getHeight(): number;
|
|
148
179
|
/**
|
|
149
|
-
*
|
|
180
|
+
* 设置画面顺时针旋转角度
|
|
150
181
|
*
|
|
151
|
-
*
|
|
182
|
+
* 仅对窗口渲染模式生效。
|
|
183
|
+
*
|
|
184
|
+
* @param rotation - 旋转角度,参考 {@link TRTCVideoRotation} 枚举,
|
|
185
|
+
* 支持 TRTCVideoRotation0 / 90 / 180 / 270,默认 TRTCVideoRotation0
|
|
152
186
|
*/
|
|
153
187
|
setRenderRotation(rotation: TRTCVideoRotation): void;
|
|
154
188
|
/**
|
|
155
189
|
* 设置画面填充模式
|
|
156
190
|
*
|
|
157
|
-
*
|
|
191
|
+
* 仅对窗口渲染模式生效。
|
|
192
|
+
*
|
|
193
|
+
* @param mode - 填充模式,参考 {@link TRTCVideoFillMode} 枚举:
|
|
194
|
+
* - Fill:画面填满窗口,可能被拉伸或裁剪
|
|
195
|
+
* - Fit:画面按比例适配窗口,可能出现黑边(默认值)
|
|
158
196
|
*/
|
|
159
197
|
setFillMode(mode: TRTCVideoFillMode): void;
|
|
160
198
|
/**
|
|
@@ -172,28 +210,32 @@ export declare class VodPlayer {
|
|
|
172
210
|
/**
|
|
173
211
|
* 设置播放音量
|
|
174
212
|
*
|
|
175
|
-
* @param volume - 音量大小,取值范围 0
|
|
213
|
+
* @param volume - 音量大小,取值范围 [0, 150],100 为原始音量,默认值 100
|
|
176
214
|
*/
|
|
177
215
|
setVolume(volume: number): void;
|
|
178
216
|
/**
|
|
179
|
-
*
|
|
217
|
+
* 向已关联的 TRTC 实例推送视频流
|
|
218
|
+
*
|
|
219
|
+
* @note 推流前播放器需已关联到 TRTC 实例(内部由 {@link start} 自动处理)。
|
|
180
220
|
*/
|
|
181
221
|
publishVideo(): void;
|
|
182
222
|
/**
|
|
183
|
-
*
|
|
223
|
+
* 向已关联的 TRTC 实例推送音频流
|
|
224
|
+
*
|
|
225
|
+
* @note 绑定后音频播放由 TRTC 接管。
|
|
184
226
|
*/
|
|
185
227
|
publishAudio(): void;
|
|
186
228
|
/**
|
|
187
|
-
*
|
|
229
|
+
* 停止向已关联的 TRTC 实例推送视频流
|
|
188
230
|
*/
|
|
189
231
|
unpublishVideo(): void;
|
|
190
232
|
/**
|
|
191
|
-
*
|
|
233
|
+
* 停止向已关联的 TRTC 实例推送音频流
|
|
192
234
|
*/
|
|
193
235
|
unpublishAudio(): void;
|
|
194
236
|
/**
|
|
195
237
|
* @private
|
|
196
|
-
* 将点播播放器关联到 TRTC
|
|
238
|
+
* 将点播播放器关联到 TRTC 实例(用于辅助流推流,绑定后音频播放由 TRTC 接管)
|
|
197
239
|
*/
|
|
198
240
|
private attachTRTC;
|
|
199
241
|
/**
|
|
@@ -201,9 +243,15 @@ export declare class VodPlayer {
|
|
|
201
243
|
* 将点播播放器从 TRTC 实例分离
|
|
202
244
|
*/
|
|
203
245
|
private detachTRTC;
|
|
246
|
+
/**
|
|
247
|
+
* 类型安全地发射事件,参数类型由 `VodPlayerEventMap` 推导。
|
|
248
|
+
* 通过 `setImmediate` 让 emit 异步化,避免在 N-API 回调栈中触发用户代码。
|
|
249
|
+
*/
|
|
204
250
|
private fire;
|
|
205
251
|
private _createVideoRender;
|
|
206
252
|
private _destroyVideoRender;
|
|
253
|
+
private _prepareRender;
|
|
254
|
+
private _teardownRender;
|
|
207
255
|
private _setVideoRenderBuffer;
|
|
208
256
|
private _addDataRenderCallback;
|
|
209
257
|
private _removeDataRenderCallback;
|
package/liteav/vod_player.js
CHANGED
|
@@ -1,29 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VodPlayer =
|
|
3
|
+
exports.VodPlayer = void 0;
|
|
4
4
|
const events_1 = require("events");
|
|
5
5
|
const trtc_define_1 = require("./trtc_define");
|
|
6
6
|
const video_render_1 = require("./Live/video-render");
|
|
7
7
|
const logger_1 = require("./logger");
|
|
8
|
+
const types_1 = require("./types");
|
|
8
9
|
const NodeTRTCEngine = require('../build/Release/trtc_electron_sdk.node');
|
|
9
|
-
/**
|
|
10
|
-
* VodPlayer 播放器事件枚举
|
|
11
|
-
*/
|
|
12
|
-
var VodPlayerEvents;
|
|
13
|
-
(function (VodPlayerEvents) {
|
|
14
|
-
/** 播放开始,参数:msLength(总时长,毫秒) */
|
|
15
|
-
VodPlayerEvents["onVodPlayerStarted"] = "onVodPlayerStarted";
|
|
16
|
-
/** 播放进度更新,参数:msPos(当前进度,毫秒) */
|
|
17
|
-
VodPlayerEvents["onVodPlayerProgress"] = "onVodPlayerProgress";
|
|
18
|
-
/** 播放暂停 */
|
|
19
|
-
VodPlayerEvents["onVodPlayerPaused"] = "onVodPlayerPaused";
|
|
20
|
-
/** 播放恢复 */
|
|
21
|
-
VodPlayerEvents["onVodPlayerResumed"] = "onVodPlayerResumed";
|
|
22
|
-
/** 播放停止,参数:reason(0=用户主动停止,1=文件播放完,2=视频断流) */
|
|
23
|
-
VodPlayerEvents["onVodPlayerStopped"] = "onVodPlayerStopped";
|
|
24
|
-
/** 播放错误,参数:error(错误码) */
|
|
25
|
-
VodPlayerEvents["onVodPlayerError"] = "onVodPlayerError";
|
|
26
|
-
})(VodPlayerEvents = exports.VodPlayerEvents || (exports.VodPlayerEvents = {}));
|
|
27
10
|
/**
|
|
28
11
|
*
|
|
29
12
|
* 腾讯云点播播放器
|
|
@@ -54,9 +37,10 @@ class VodPlayer {
|
|
|
54
37
|
this._dataRenderCallback = this._dataRenderCallback.bind(this);
|
|
55
38
|
this.nativeVodPlayer = new NodeTRTCEngine.NodeVodPlayer(mediaFilePath, repeat);
|
|
56
39
|
this.mediaFilePath = mediaFilePath;
|
|
57
|
-
this.repeat = repeat;
|
|
58
40
|
this.isStarted = false;
|
|
59
41
|
this.isDestroyed = false;
|
|
42
|
+
this.isRenderPrepared = false;
|
|
43
|
+
this._setBufferRetryCount = 0;
|
|
60
44
|
this.videoRender = null;
|
|
61
45
|
this._createVideoRender();
|
|
62
46
|
this._initEventCallback();
|
|
@@ -65,11 +49,17 @@ class VodPlayer {
|
|
|
65
49
|
/**
|
|
66
50
|
* 创建 VodPlayer 实例
|
|
67
51
|
*
|
|
68
|
-
* @param mediaFilePath -
|
|
52
|
+
* @param mediaFilePath - 媒体文件路径(本地绝对路径或在线 URL),必填且必须是非空字符串
|
|
69
53
|
* @param repeat - 是否循环播放,默认 false
|
|
70
54
|
* @returns VodPlayer 实例
|
|
55
|
+
*
|
|
56
|
+
* @throws {TypeError} 当 `mediaFilePath` 不是非空字符串时抛出
|
|
71
57
|
*/
|
|
72
58
|
static createVodPlayer(mediaFilePath, repeat = false) {
|
|
59
|
+
if (typeof mediaFilePath !== 'string' || mediaFilePath.length === 0) {
|
|
60
|
+
// 空串或非字符串透传到 C++ 后 createTXVodPlayer 行为未定义,提前抛错让调用方立刻发现
|
|
61
|
+
throw new TypeError(`VodPlayer.createVodPlayer: mediaFilePath must be a non-empty string, got: ${JSON.stringify(mediaFilePath)}`);
|
|
62
|
+
}
|
|
73
63
|
return new VodPlayer(mediaFilePath, repeat);
|
|
74
64
|
}
|
|
75
65
|
/**
|
|
@@ -112,23 +102,72 @@ class VodPlayer {
|
|
|
112
102
|
/**
|
|
113
103
|
* 设置视频渲染的 DOM 容器
|
|
114
104
|
*
|
|
115
|
-
* @param view - HTML
|
|
105
|
+
* @param view - HTML 元素,用于承载视频画面;传 `null` 时仅解除当前 view 关联,
|
|
106
|
+
* 播放/渲染管线不受影响(可后续再次 `setView(newDom)` 切换容器)。
|
|
107
|
+
*
|
|
108
|
+
* @note 若调用方需要彻底停止渲染,请使用 {@link stop} 或 {@link destroy}。
|
|
116
109
|
*/
|
|
117
110
|
setView(view) {
|
|
118
|
-
var _a;
|
|
111
|
+
var _a, _b;
|
|
119
112
|
if (this.isDestroyed) {
|
|
120
113
|
this.logger.warn('setView: player already destroyed');
|
|
121
114
|
return;
|
|
122
115
|
}
|
|
116
|
+
if (view === null) {
|
|
117
|
+
// 仅解除 view 关联,不下发 destroyRender / removeDataRenderCallback
|
|
118
|
+
// 否则后续 setView(newDom) 还需要重建整条渲染管线
|
|
119
|
+
this.logger.info('setView: view is null, detach current view');
|
|
120
|
+
(_a = this.videoRender) === null || _a === void 0 ? void 0 : _a.setRenderView(null);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
123
|
this.logger.info(`setView view: ${view}`);
|
|
124
|
-
(
|
|
124
|
+
(_b = this.videoRender) === null || _b === void 0 ? void 0 : _b.setRenderView(view);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 预加载多媒体文件
|
|
128
|
+
*
|
|
129
|
+
* 预加载完成后会触发 {@link VodPlayerEvents.onVodPlayerLoaded} 事件,事件参数携带
|
|
130
|
+
* 媒体信息(时长、宽高);同时 C++ 层会产生首帧并推送到 JS 层的视频渲染管线,
|
|
131
|
+
* 在 view 上展示首帧画面。
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* player.on(VodPlayerEvents.onVodPlayerLoaded, (durationMs, width, height) => {
|
|
135
|
+
* console.log('预加载完成:', durationMs, width, height);
|
|
136
|
+
* player.start();
|
|
137
|
+
* });
|
|
138
|
+
* player.preload();
|
|
139
|
+
*
|
|
140
|
+
* @note 可以先调用 preload 再调用 {@link start} 播放,也可以不调用 preload 直接调用 {@link start}。
|
|
141
|
+
* @note 若已经调用过 {@link start},再调用 preload 将无效。
|
|
142
|
+
*/
|
|
143
|
+
preload() {
|
|
144
|
+
var _a;
|
|
145
|
+
if (this.isDestroyed) {
|
|
146
|
+
this.logger.warn('preload: player already destroyed');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (this.isStarted) {
|
|
150
|
+
this.logger.warn('preload: already started, ignored');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.logger.info(`preload mediaFile: ${this.mediaFilePath}`);
|
|
154
|
+
this._prepareRender();
|
|
155
|
+
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.preload();
|
|
125
156
|
}
|
|
126
157
|
/**
|
|
127
158
|
* 开始播放
|
|
128
159
|
*
|
|
160
|
+
* 支持的视频格式:mp4、mkv、mov。
|
|
161
|
+
* 支持的音频格式:opus、aac。
|
|
162
|
+
*
|
|
163
|
+
* 重复调用会被忽略。
|
|
164
|
+
*
|
|
165
|
+
* @note 可以先调用 {@link preload} 预加载完成后再调用 start,也可以跳过 preload 直接调用 start。
|
|
166
|
+
* @note 从 SDK 10.7 版本开始,需要通过 TXLiveBase#setLicence 设置 Licence 后方可成功播放,
|
|
167
|
+
* 否则将播放失败(黑屏),全局仅设置一次即可。
|
|
129
168
|
*/
|
|
130
169
|
start() {
|
|
131
|
-
var _a
|
|
170
|
+
var _a;
|
|
132
171
|
if (this.isDestroyed) {
|
|
133
172
|
this.logger.warn('start: player already destroyed');
|
|
134
173
|
return;
|
|
@@ -138,35 +177,35 @@ class VodPlayer {
|
|
|
138
177
|
this.logger.warn('start: already started, ignored');
|
|
139
178
|
return;
|
|
140
179
|
}
|
|
141
|
-
|
|
142
|
-
this._setVideoRenderBuffer();
|
|
143
|
-
this._addDataRenderCallback();
|
|
180
|
+
this._prepareRender();
|
|
144
181
|
this.attachTRTC();
|
|
145
|
-
(
|
|
182
|
+
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.start();
|
|
146
183
|
this.isStarted = true;
|
|
147
184
|
}
|
|
148
185
|
/**
|
|
149
186
|
* 停止播放
|
|
150
|
-
*
|
|
151
187
|
*/
|
|
152
188
|
stop() {
|
|
153
|
-
var _a
|
|
189
|
+
var _a;
|
|
154
190
|
if (this.isDestroyed) {
|
|
155
191
|
this.logger.warn('stop: player already destroyed');
|
|
156
192
|
return;
|
|
157
193
|
}
|
|
158
194
|
this.logger.info('stop');
|
|
159
|
-
if (!this.isStarted) {
|
|
195
|
+
if (!this.isStarted && !this.isRenderPrepared) {
|
|
160
196
|
return;
|
|
161
197
|
}
|
|
162
|
-
this.isStarted
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
198
|
+
if (this.isStarted) {
|
|
199
|
+
this.isStarted = false;
|
|
200
|
+
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.stop();
|
|
201
|
+
this.detachTRTC();
|
|
202
|
+
}
|
|
203
|
+
this._teardownRender();
|
|
167
204
|
}
|
|
168
205
|
/**
|
|
169
206
|
* 暂停播放
|
|
207
|
+
*
|
|
208
|
+
* @note 仅在 {@link start} 之后调用才有效;未播放时调用会被忽略并打 warn 日志。
|
|
170
209
|
*/
|
|
171
210
|
pause() {
|
|
172
211
|
var _a;
|
|
@@ -174,11 +213,17 @@ class VodPlayer {
|
|
|
174
213
|
this.logger.warn('pause: player already destroyed');
|
|
175
214
|
return;
|
|
176
215
|
}
|
|
216
|
+
if (!this.isStarted) {
|
|
217
|
+
this.logger.warn('pause: player not started, ignored');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
177
220
|
this.logger.info('pause');
|
|
178
221
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.pause();
|
|
179
222
|
}
|
|
180
223
|
/**
|
|
181
224
|
* 恢复播放
|
|
225
|
+
*
|
|
226
|
+
* @note 仅在 {@link start} 之后调用才有效;未播放时调用会被忽略并打 warn 日志。
|
|
182
227
|
*/
|
|
183
228
|
resume() {
|
|
184
229
|
var _a;
|
|
@@ -186,13 +231,19 @@ class VodPlayer {
|
|
|
186
231
|
this.logger.warn('resume: player already destroyed');
|
|
187
232
|
return;
|
|
188
233
|
}
|
|
234
|
+
if (!this.isStarted) {
|
|
235
|
+
this.logger.warn('resume: player not started, ignored');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
189
238
|
this.logger.info('resume');
|
|
190
239
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.resume();
|
|
191
240
|
}
|
|
192
241
|
/**
|
|
193
|
-
*
|
|
242
|
+
* 跳转到指定播放位置(seek)
|
|
194
243
|
*
|
|
195
244
|
* @param msPos - 目标位置,单位毫秒
|
|
245
|
+
*
|
|
246
|
+
* @note 调用前必须先 {@link preload} 或 {@link start},否则会被忽略并打 warn 日志。
|
|
196
247
|
*/
|
|
197
248
|
seek(msPos) {
|
|
198
249
|
var _a;
|
|
@@ -200,13 +251,54 @@ class VodPlayer {
|
|
|
200
251
|
this.logger.warn('seek: player already destroyed');
|
|
201
252
|
return;
|
|
202
253
|
}
|
|
254
|
+
if (!this.isStarted && !this.isRenderPrepared) {
|
|
255
|
+
this.logger.warn(`seek: player not preloaded or started, ignored (msPos=${msPos})`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
203
258
|
this.logger.info(`seek msPos: ${msPos}`);
|
|
204
259
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.seek(msPos);
|
|
205
260
|
}
|
|
206
261
|
/**
|
|
207
|
-
*
|
|
262
|
+
* 无缝切换当前播放的媒体文件
|
|
263
|
+
*
|
|
264
|
+
* 在后台预加载新的媒体源,待新源就绪后无缝切换,避免切换时出现黑屏。
|
|
265
|
+
* 切换成功后触发 {@link VodPlayerEvents.onVodPlayerLoaded} 事件,携带新文件的媒体信息。
|
|
266
|
+
*
|
|
267
|
+
* @param newMediaFile - 新的媒体文件路径或 URL
|
|
268
|
+
*
|
|
269
|
+
* @note 若当前处于暂停状态,切换后仍保持暂停并展示新文件第一帧。
|
|
270
|
+
* @note 切换过程中调用 {@link stop} 会取消切换并停止当前播放。
|
|
271
|
+
* @note 调用前必须先 {@link preload} 或 {@link start},否则会被忽略并打 warn 日志。
|
|
272
|
+
* @note 传入空串会被忽略并打 warn 日志(C++ 层亦有同等保护)。
|
|
273
|
+
*/
|
|
274
|
+
switchSource(newMediaFile) {
|
|
275
|
+
var _a;
|
|
276
|
+
if (this.isDestroyed) {
|
|
277
|
+
this.logger.warn('switchSource: player already destroyed');
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (!newMediaFile) {
|
|
281
|
+
this.logger.warn('switchSource: newMediaFile is empty, ignored');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!this.isStarted && !this.isRenderPrepared) {
|
|
285
|
+
this.logger.warn(`switchSource: player not preloaded or started, ignored (newMediaFile=${newMediaFile})`);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
this.logger.info(`switchSource newMediaFile: ${newMediaFile}`);
|
|
289
|
+
this.mediaFilePath = newMediaFile;
|
|
290
|
+
// 切换源后如果出现 buffer 尺寸变化,需要让 _dataRenderCallback 退避计数重置
|
|
291
|
+
this._setBufferRetryCount = 0;
|
|
292
|
+
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.switchSource(newMediaFile);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* 获取视频总时长
|
|
296
|
+
*
|
|
297
|
+
* @returns 总时长,单位毫秒;播放器已销毁时返回 0。
|
|
208
298
|
*
|
|
209
|
-
* @
|
|
299
|
+
* @note 跨平台口径已统一为 `int64_t`(即使 Windows x64 下底层 `long` 是 32 位,
|
|
300
|
+
* binding 层也会显式扩到 64 位避免 ~49 天回绕);JS `number` 安全整数上限 2^53,
|
|
301
|
+
* 业务上点播时长不会触及。
|
|
210
302
|
*/
|
|
211
303
|
getDuration() {
|
|
212
304
|
var _a, _b;
|
|
@@ -219,7 +311,7 @@ class VodPlayer {
|
|
|
219
311
|
/**
|
|
220
312
|
* 获取视频宽度
|
|
221
313
|
*
|
|
222
|
-
* @returns
|
|
314
|
+
* @returns 视频宽度(像素);纯音频文件或播放器已销毁时返回 0
|
|
223
315
|
*/
|
|
224
316
|
getWidth() {
|
|
225
317
|
var _a, _b;
|
|
@@ -232,7 +324,7 @@ class VodPlayer {
|
|
|
232
324
|
/**
|
|
233
325
|
* 获取视频高度
|
|
234
326
|
*
|
|
235
|
-
* @returns
|
|
327
|
+
* @returns 视频高度(像素);纯音频文件或播放器已销毁时返回 0
|
|
236
328
|
*/
|
|
237
329
|
getHeight() {
|
|
238
330
|
var _a, _b;
|
|
@@ -243,9 +335,12 @@ class VodPlayer {
|
|
|
243
335
|
return (_b = (_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.getHeight()) !== null && _b !== void 0 ? _b : 0;
|
|
244
336
|
}
|
|
245
337
|
/**
|
|
246
|
-
*
|
|
338
|
+
* 设置画面顺时针旋转角度
|
|
339
|
+
*
|
|
340
|
+
* 仅对窗口渲染模式生效。
|
|
247
341
|
*
|
|
248
|
-
* @param rotation - 旋转角度,参考 TRTCVideoRotation
|
|
342
|
+
* @param rotation - 旋转角度,参考 {@link TRTCVideoRotation} 枚举,
|
|
343
|
+
* 支持 TRTCVideoRotation0 / 90 / 180 / 270,默认 TRTCVideoRotation0
|
|
249
344
|
*/
|
|
250
345
|
setRenderRotation(rotation) {
|
|
251
346
|
var _a;
|
|
@@ -259,7 +354,11 @@ class VodPlayer {
|
|
|
259
354
|
/**
|
|
260
355
|
* 设置画面填充模式
|
|
261
356
|
*
|
|
262
|
-
*
|
|
357
|
+
* 仅对窗口渲染模式生效。
|
|
358
|
+
*
|
|
359
|
+
* @param mode - 填充模式,参考 {@link TRTCVideoFillMode} 枚举:
|
|
360
|
+
* - Fill:画面填满窗口,可能被拉伸或裁剪
|
|
361
|
+
* - Fit:画面按比例适配窗口,可能出现黑边(默认值)
|
|
263
362
|
*/
|
|
264
363
|
setFillMode(mode) {
|
|
265
364
|
var _a, _b;
|
|
@@ -302,7 +401,7 @@ class VodPlayer {
|
|
|
302
401
|
/**
|
|
303
402
|
* 设置播放音量
|
|
304
403
|
*
|
|
305
|
-
* @param volume - 音量大小,取值范围 0
|
|
404
|
+
* @param volume - 音量大小,取值范围 [0, 150],100 为原始音量,默认值 100
|
|
306
405
|
*/
|
|
307
406
|
setVolume(volume) {
|
|
308
407
|
var _a;
|
|
@@ -314,7 +413,9 @@ class VodPlayer {
|
|
|
314
413
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.setVolume(volume);
|
|
315
414
|
}
|
|
316
415
|
/**
|
|
317
|
-
*
|
|
416
|
+
* 向已关联的 TRTC 实例推送视频流
|
|
417
|
+
*
|
|
418
|
+
* @note 推流前播放器需已关联到 TRTC 实例(内部由 {@link start} 自动处理)。
|
|
318
419
|
*/
|
|
319
420
|
publishVideo() {
|
|
320
421
|
var _a;
|
|
@@ -326,7 +427,9 @@ class VodPlayer {
|
|
|
326
427
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.publishVideo();
|
|
327
428
|
}
|
|
328
429
|
/**
|
|
329
|
-
*
|
|
430
|
+
* 向已关联的 TRTC 实例推送音频流
|
|
431
|
+
*
|
|
432
|
+
* @note 绑定后音频播放由 TRTC 接管。
|
|
330
433
|
*/
|
|
331
434
|
publishAudio() {
|
|
332
435
|
var _a;
|
|
@@ -338,7 +441,7 @@ class VodPlayer {
|
|
|
338
441
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.publishAudio();
|
|
339
442
|
}
|
|
340
443
|
/**
|
|
341
|
-
*
|
|
444
|
+
* 停止向已关联的 TRTC 实例推送视频流
|
|
342
445
|
*/
|
|
343
446
|
unpublishVideo() {
|
|
344
447
|
var _a;
|
|
@@ -350,7 +453,7 @@ class VodPlayer {
|
|
|
350
453
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.unpublishVideo();
|
|
351
454
|
}
|
|
352
455
|
/**
|
|
353
|
-
*
|
|
456
|
+
* 停止向已关联的 TRTC 实例推送音频流
|
|
354
457
|
*/
|
|
355
458
|
unpublishAudio() {
|
|
356
459
|
var _a;
|
|
@@ -364,7 +467,7 @@ class VodPlayer {
|
|
|
364
467
|
// ─── 内部方法 ───────────────────────────────────────────────
|
|
365
468
|
/**
|
|
366
469
|
* @private
|
|
367
|
-
* 将点播播放器关联到 TRTC
|
|
470
|
+
* 将点播播放器关联到 TRTC 实例(用于辅助流推流,绑定后音频播放由 TRTC 接管)
|
|
368
471
|
*/
|
|
369
472
|
attachTRTC() {
|
|
370
473
|
var _a;
|
|
@@ -388,6 +491,10 @@ class VodPlayer {
|
|
|
388
491
|
this.logger.info('detachTRTC');
|
|
389
492
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.detachTRTC();
|
|
390
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* 类型安全地发射事件,参数类型由 `VodPlayerEventMap` 推导。
|
|
496
|
+
* 通过 `setImmediate` 让 emit 异步化,避免在 N-API 回调栈中触发用户代码。
|
|
497
|
+
*/
|
|
391
498
|
fire(event, ...args) {
|
|
392
499
|
setImmediate(() => {
|
|
393
500
|
this.eventEmitter.emit(event, ...args);
|
|
@@ -401,11 +508,32 @@ class VodPlayer {
|
|
|
401
508
|
this.videoRender.setVideoPixelFormat(trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32);
|
|
402
509
|
}
|
|
403
510
|
_destroyVideoRender() {
|
|
511
|
+
this._teardownRender();
|
|
404
512
|
if (this.videoRender) {
|
|
405
513
|
this.videoRender.destroy();
|
|
406
514
|
this.videoRender = null;
|
|
407
515
|
}
|
|
516
|
+
}
|
|
517
|
+
_prepareRender() {
|
|
518
|
+
var _a;
|
|
519
|
+
if (this.isRenderPrepared) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
(_a = this.videoRender) === null || _a === void 0 ? void 0 : _a.createRender();
|
|
523
|
+
this._setVideoRenderBuffer();
|
|
524
|
+
this._addDataRenderCallback();
|
|
525
|
+
this.isRenderPrepared = true;
|
|
526
|
+
this._setBufferRetryCount = 0;
|
|
527
|
+
}
|
|
528
|
+
_teardownRender() {
|
|
529
|
+
var _a;
|
|
530
|
+
if (!this.isRenderPrepared) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
(_a = this.videoRender) === null || _a === void 0 ? void 0 : _a.destroyRender();
|
|
408
534
|
this._removeDataRenderCallback();
|
|
535
|
+
this.isRenderPrepared = false;
|
|
536
|
+
this._setBufferRetryCount = 0;
|
|
409
537
|
}
|
|
410
538
|
_setVideoRenderBuffer() {
|
|
411
539
|
var _a;
|
|
@@ -424,47 +552,69 @@ class VodPlayer {
|
|
|
424
552
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.setDataCallback(null);
|
|
425
553
|
}
|
|
426
554
|
_dataRenderCallback(args) {
|
|
427
|
-
if (this.videoRender) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
555
|
+
if (!this.videoRender) {
|
|
556
|
+
this.logger.warn('_dataRenderCallback: videoRender is null, frame dropped');
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
const [userId, type, width, height, timestamp, rotation, valid, bufferId] = args;
|
|
560
|
+
const result = this.videoRender.renderVideoData(userId, type, width, height, timestamp, rotation, valid, bufferId);
|
|
561
|
+
if (result) {
|
|
562
|
+
// 渲染成功,重置重试计数,避免长期累计后误触发降级
|
|
563
|
+
if (this._setBufferRetryCount !== 0) {
|
|
564
|
+
this._setBufferRetryCount = 0;
|
|
433
565
|
}
|
|
566
|
+
return;
|
|
434
567
|
}
|
|
435
|
-
|
|
436
|
-
|
|
568
|
+
// renderVideoData 返回 false 通常意味着 buffer 尺寸 / 格式不匹配,需要重新 setVideoBuffer。
|
|
569
|
+
// 但若底层持续失败(例如尺寸一直对不上),不能每帧都重置 buffer——30fps 下每秒会触发 30 次
|
|
570
|
+
// 跨 N-API 调用,引发明显性能抖动。这里加重试上限:前 N 次正常重置,超过后退避到周期性日志。
|
|
571
|
+
this._setBufferRetryCount += 1;
|
|
572
|
+
if (this._setBufferRetryCount <= VodPlayer.MAX_BUFFER_RETRY) {
|
|
573
|
+
this.logger.info(`_dataRenderCallback: renderVideoData returned false (retry ${this._setBufferRetryCount}/${VodPlayer.MAX_BUFFER_RETRY}), re-setting video buffer`);
|
|
574
|
+
this._setVideoRenderBuffer();
|
|
575
|
+
}
|
|
576
|
+
else if (this._setBufferRetryCount % VodPlayer.BUFFER_RETRY_LOG_INTERVAL === 0) {
|
|
577
|
+
this.logger.warn(`_dataRenderCallback: renderVideoData keeps failing for ${this._setBufferRetryCount} frames, giving up frame`);
|
|
437
578
|
}
|
|
438
579
|
}
|
|
439
580
|
_initEventCallback() {
|
|
440
581
|
var _a;
|
|
441
582
|
(_a = this.nativeVodPlayer) === null || _a === void 0 ? void 0 : _a.setEventCallback((args) => {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
583
|
+
switch (args[0]) {
|
|
584
|
+
case types_1.VodPlayerEvents.onVodPlayerStarted:
|
|
585
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerStarted, args[1].msLength);
|
|
586
|
+
break;
|
|
587
|
+
case types_1.VodPlayerEvents.onVodPlayerLoaded: {
|
|
588
|
+
const data = args[1];
|
|
589
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerLoaded, data.durationMs, data.width, data.height);
|
|
447
590
|
break;
|
|
448
|
-
|
|
449
|
-
|
|
591
|
+
}
|
|
592
|
+
case types_1.VodPlayerEvents.onVodPlayerProgress:
|
|
593
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerProgress, args[1].msPos);
|
|
450
594
|
break;
|
|
451
|
-
case VodPlayerEvents.onVodPlayerPaused:
|
|
452
|
-
this.fire(VodPlayerEvents.onVodPlayerPaused);
|
|
595
|
+
case types_1.VodPlayerEvents.onVodPlayerPaused:
|
|
596
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerPaused);
|
|
453
597
|
break;
|
|
454
|
-
case VodPlayerEvents.onVodPlayerResumed:
|
|
455
|
-
this.fire(VodPlayerEvents.onVodPlayerResumed);
|
|
598
|
+
case types_1.VodPlayerEvents.onVodPlayerResumed:
|
|
599
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerResumed);
|
|
456
600
|
break;
|
|
457
|
-
case VodPlayerEvents.onVodPlayerStopped:
|
|
458
|
-
this.fire(VodPlayerEvents.onVodPlayerStopped,
|
|
601
|
+
case types_1.VodPlayerEvents.onVodPlayerStopped:
|
|
602
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerStopped, args[1].reason);
|
|
459
603
|
break;
|
|
460
|
-
case VodPlayerEvents.onVodPlayerError:
|
|
461
|
-
this.fire(VodPlayerEvents.onVodPlayerError,
|
|
604
|
+
case types_1.VodPlayerEvents.onVodPlayerError:
|
|
605
|
+
this.fire(types_1.VodPlayerEvents.onVodPlayerError, args[1].error);
|
|
462
606
|
break;
|
|
463
|
-
default:
|
|
464
|
-
|
|
607
|
+
default: {
|
|
608
|
+
const exhaustiveCheck = args[0];
|
|
609
|
+
this.logger.warn(`unknown vod player event: ${String(exhaustiveCheck)}`);
|
|
465
610
|
break;
|
|
611
|
+
}
|
|
466
612
|
}
|
|
467
613
|
});
|
|
468
614
|
}
|
|
469
615
|
}
|
|
470
616
|
exports.VodPlayer = VodPlayer;
|
|
617
|
+
/** `_dataRenderCallback` 中允许连续重置 video buffer 的最大次数,超过后退化为周期日志 */
|
|
618
|
+
VodPlayer.MAX_BUFFER_RETRY = 3;
|
|
619
|
+
/** 重试上限达到后,每隔多少帧打一次 warn 日志(按 30fps 估算 ≈ 2 秒一次) */
|
|
620
|
+
VodPlayer.BUFFER_RETRY_LOG_INTERVAL = 60;
|