@ray-js/ray-ipc-player 2.1.0 → 2.1.1-beta.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/lib/hooks/usePlayerProps.js +7 -3
- package/lib/index.js +121 -47
- package/lib/typings/index.d.ts +22 -6
- package/package.json +1 -1
|
@@ -43,8 +43,10 @@ export const usePlayerProps = props => {
|
|
|
43
43
|
hideHelpButton = false,
|
|
44
44
|
hideFeedBackButton = false,
|
|
45
45
|
playerRoute = '',
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
previewEnabled,
|
|
47
|
+
onPreviewEnabledChange,
|
|
48
|
+
limitFlow = false,
|
|
49
|
+
autoWakeUp = false
|
|
48
50
|
} = props;
|
|
49
51
|
|
|
50
52
|
// 解构 playerStyle
|
|
@@ -83,8 +85,10 @@ export const usePlayerProps = props => {
|
|
|
83
85
|
hideHelpButton,
|
|
84
86
|
hideFeedBackButton,
|
|
85
87
|
playerRoute,
|
|
86
|
-
|
|
88
|
+
previewEnabled,
|
|
89
|
+
onPreviewEnabledChange,
|
|
87
90
|
limitFlow,
|
|
91
|
+
autoWakeUp,
|
|
88
92
|
// 样式相关
|
|
89
93
|
borderRadius,
|
|
90
94
|
bgColor,
|
package/lib/index.js
CHANGED
|
@@ -54,8 +54,10 @@ const Player = props => {
|
|
|
54
54
|
hideHelpButton,
|
|
55
55
|
hideFeedBackButton,
|
|
56
56
|
playerRoute,
|
|
57
|
-
|
|
57
|
+
previewEnabled,
|
|
58
|
+
onPreviewEnabledChange,
|
|
58
59
|
limitFlow,
|
|
60
|
+
autoWakeUp,
|
|
59
61
|
borderRadius,
|
|
60
62
|
bgColor,
|
|
61
63
|
borderStyle,
|
|
@@ -94,8 +96,9 @@ const Player = props => {
|
|
|
94
96
|
const privateLowPowerDeviceTimeOutRef = useRef(null);
|
|
95
97
|
const privateWakeOutTimeRef = useRef(null);
|
|
96
98
|
const privateDeviceWakeNeedPublishTimeRef = useRef(null);
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
+
/** 传入 previewEnabled 为受控;未传时 previewOn 为 true(自动拉流) */
|
|
100
|
+
const isPreviewControlled = previewEnabled !== undefined;
|
|
101
|
+
const previewOn = previewEnabled !== null && previewEnabled !== void 0 ? previewEnabled : true;
|
|
99
102
|
|
|
100
103
|
// connectChangeRef
|
|
101
104
|
useRef(null);
|
|
@@ -103,6 +106,8 @@ const Player = props => {
|
|
|
103
106
|
|
|
104
107
|
// 标记是否进入内存缓存/后台(onPause、onHide 设为 true,onShow 还原为 false),拉流时若为 true 则拦截
|
|
105
108
|
const isInBackgroundRef = useRef(false);
|
|
109
|
+
/** 受控 previewEnabled:因 onHide/onPause 已通知父级 false,回到前台时需恢复 true 并拉流 */
|
|
110
|
+
const previewPausedByLifecycleRef = useRef(false);
|
|
106
111
|
|
|
107
112
|
// 自定义计时老低功耗方案设备在线状态, 用于短暂时间报上下线的UI展示兼容 待实现
|
|
108
113
|
const [lowPowerDeviceOnlineState, setLowPowerDeviceOnlineState] = useState(onlineStatus);
|
|
@@ -171,6 +176,66 @@ const Player = props => {
|
|
|
171
176
|
});
|
|
172
177
|
}
|
|
173
178
|
});
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 实际发起拉流(隐私唤醒 + P2P/预览),与是否受控无关
|
|
182
|
+
*/
|
|
183
|
+
const runPullStream = useMemoizedFn(() => {
|
|
184
|
+
phoneNetworkConnect && onlineStatus && privateState && (!isLowPowerDevice || isVirtualDevice) && handleReWakeCamera();
|
|
185
|
+
phoneNetworkConnect && onlineStatus && privateState && isLowPowerDevice && !isVirtualDevice && handleReWakeCameraLowPowerDevice();
|
|
186
|
+
phoneNetworkConnect && onlineStatus && !privateState && _retry();
|
|
187
|
+
});
|
|
188
|
+
const retry = useMemoizedFn(() => {
|
|
189
|
+
console.log('重新拉流启动');
|
|
190
|
+
// 任何重试拉流时, 将播放器状态还原为loading状态
|
|
191
|
+
setVideoErrCode('');
|
|
192
|
+
setPlayState(d => {
|
|
193
|
+
d.loadingState = true;
|
|
194
|
+
d.errorState = false;
|
|
195
|
+
d.errorMsg = '';
|
|
196
|
+
});
|
|
197
|
+
// 排除默认值为"",不等于播放器路由时, 不进行重试拉流
|
|
198
|
+
|
|
199
|
+
if (playerRoute !== '' && playerRoute !== getPlayerRoute()) {
|
|
200
|
+
console.log('不在播放器路由内, 不进行拉流');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (isInBackgroundRef.current) {
|
|
204
|
+
console.log('处于后台/内存缓存,拦截拉流');
|
|
205
|
+
ipcTTTOperatorLog('VID: isInBackground, block retry');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (isPreviewControlled) {
|
|
209
|
+
onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(true);
|
|
210
|
+
if (previewEnabled) {
|
|
211
|
+
runPullStream();
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
runPullStream();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 命令式开关:受控走 onPreviewEnabledChange;未传 previewEnabled 时 previewOn 恒为 true,仅支持开启拉流(retry)
|
|
220
|
+
*/
|
|
221
|
+
const setPreviewEnabledCommand = useMemoizedFn(enabled => {
|
|
222
|
+
if (isPreviewControlled) {
|
|
223
|
+
onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(enabled);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (enabled) {
|
|
227
|
+
retry();
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// 创建ipc实例
|
|
232
|
+
const createIpcCtx = () => {
|
|
233
|
+
onCtx && onCtx({
|
|
234
|
+
ctx: ipcCtx.current,
|
|
235
|
+
retry,
|
|
236
|
+
setPreviewEnabled: setPreviewEnabledCommand
|
|
237
|
+
});
|
|
238
|
+
};
|
|
174
239
|
usePageEvent('onShow', useMemoizedFn(async () => {
|
|
175
240
|
isInBackgroundRef.current = false;
|
|
176
241
|
getNetworkType({
|
|
@@ -187,8 +252,18 @@ const Player = props => {
|
|
|
187
252
|
onChangeIgnoreHideStopPreview && onChangeIgnoreHideStopPreview(false);
|
|
188
253
|
return;
|
|
189
254
|
}
|
|
255
|
+
// 受控 preview:后台/隐藏时已把父级置为 false,前台先恢复意图再拉流(不依赖同一帧 previewOn)
|
|
256
|
+
if (previewPausedByLifecycleRef.current && isPreviewControlled) {
|
|
257
|
+
previewPausedByLifecycleRef.current = false;
|
|
258
|
+
onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(true);
|
|
259
|
+
if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow) {
|
|
260
|
+
ipcTTTOperatorLog('VID: onShow_resume_after_hide_pause');
|
|
261
|
+
runPullStream();
|
|
262
|
+
}
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
190
265
|
// 视图准备就绪
|
|
191
|
-
if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow &&
|
|
266
|
+
if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow && previewOn) {
|
|
192
267
|
ipcTTTOperatorLog('VID: onShow_event_to_retry');
|
|
193
268
|
retry();
|
|
194
269
|
}
|
|
@@ -210,7 +285,7 @@ const Player = props => {
|
|
|
210
285
|
|
|
211
286
|
// 针对limitFlow
|
|
212
287
|
useEffect(() => {
|
|
213
|
-
if (limitFlow || !
|
|
288
|
+
if (limitFlow || !previewOn) {
|
|
214
289
|
setPlayState(d => {
|
|
215
290
|
return _objectSpread(_objectSpread({}, d), {}, {
|
|
216
291
|
loadingState: false,
|
|
@@ -218,13 +293,13 @@ const Player = props => {
|
|
|
218
293
|
errorMessage: ''
|
|
219
294
|
});
|
|
220
295
|
});
|
|
221
|
-
ipcTTTOperatorLog("limitFlow ~~~~ ".concat(limitFlow, "
|
|
296
|
+
ipcTTTOperatorLog("limitFlow ~~~~ ".concat(limitFlow, " previewOn ~~~ ").concat(previewOn));
|
|
222
297
|
if (playState.initLy && ipcCtx.current) {
|
|
223
298
|
stopPreview();
|
|
224
299
|
disconnect();
|
|
225
300
|
}
|
|
226
301
|
}
|
|
227
|
-
}, [limitFlow,
|
|
302
|
+
}, [limitFlow, previewOn, playState.initLy, ipcCtx.current]);
|
|
228
303
|
useEffect(() => {
|
|
229
304
|
registerDeviceListListener({
|
|
230
305
|
deviceIdList: [devId],
|
|
@@ -260,6 +335,10 @@ const Player = props => {
|
|
|
260
335
|
if (ignoreHideStopPreview) {
|
|
261
336
|
return;
|
|
262
337
|
}
|
|
338
|
+
if (isPreviewControlled && previewOn) {
|
|
339
|
+
previewPausedByLifecycleRef.current = true;
|
|
340
|
+
onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(false);
|
|
341
|
+
}
|
|
263
342
|
setPlayState(d => {
|
|
264
343
|
d.loadingState = true;
|
|
265
344
|
});
|
|
@@ -271,6 +350,10 @@ const Player = props => {
|
|
|
271
350
|
isInBackgroundRef.current = true;
|
|
272
351
|
console.log('onPause, 重新拉流');
|
|
273
352
|
ipcTTTOperatorLog('VID: onPause stopPreview');
|
|
353
|
+
if (!ignoreHideStopPreview && isPreviewControlled && previewOn) {
|
|
354
|
+
previewPausedByLifecycleRef.current = true;
|
|
355
|
+
onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(false);
|
|
356
|
+
}
|
|
274
357
|
stopPreview();
|
|
275
358
|
disconnect();
|
|
276
359
|
}));
|
|
@@ -375,6 +458,20 @@ const Player = props => {
|
|
|
375
458
|
};
|
|
376
459
|
}, [stopPreview, disconnect]);
|
|
377
460
|
|
|
461
|
+
/**
|
|
462
|
+
* autoWakeUp 模式:视图就绪后立即开始唤醒设备,但不拉流
|
|
463
|
+
*/
|
|
464
|
+
useEffect(() => {
|
|
465
|
+
if (!(autoWakeUp && isLowPowerDevice && playState.initLy && !awakeStatus)) {
|
|
466
|
+
return undefined;
|
|
467
|
+
}
|
|
468
|
+
setEnableWakeUpInterval(true);
|
|
469
|
+
const timeout = setTimeout(() => {
|
|
470
|
+
setEnableWakeUpInterval(false);
|
|
471
|
+
}, 30000);
|
|
472
|
+
return () => clearTimeout(timeout);
|
|
473
|
+
}, [autoWakeUp, isLowPowerDevice, playState.initLy, awakeStatus]);
|
|
474
|
+
|
|
378
475
|
/**
|
|
379
476
|
* 唤醒设备TTT能力
|
|
380
477
|
*/
|
|
@@ -384,6 +481,15 @@ const Player = props => {
|
|
|
384
481
|
intervalTime: 300
|
|
385
482
|
});
|
|
386
483
|
|
|
484
|
+
/**
|
|
485
|
+
* autoWakeUp 模式下,设备进入唤醒状态后停止继续下发唤醒指令
|
|
486
|
+
*/
|
|
487
|
+
useEffect(() => {
|
|
488
|
+
if (autoWakeUp && isLowPowerDevice && awakeStatus) {
|
|
489
|
+
setEnableWakeUpInterval(false);
|
|
490
|
+
}
|
|
491
|
+
}, [awakeStatus, isLowPowerDevice, autoWakeUp]);
|
|
492
|
+
|
|
387
493
|
/**
|
|
388
494
|
* 监听设备休眠状态变化
|
|
389
495
|
* 当检测到设备上报休眠后,触发重新连接
|
|
@@ -460,7 +566,7 @@ const Player = props => {
|
|
|
460
566
|
d.errorState = true;
|
|
461
567
|
d.errorMsg = limitFlow ? Strings.getLang('ipc_player_traffic_load_offline_limit_tip') : Strings.getLang('ipc_player_device_offline');
|
|
462
568
|
});
|
|
463
|
-
} else if (!
|
|
569
|
+
} else if (!previewOn) {
|
|
464
570
|
setPlayState(d => {
|
|
465
571
|
d.errorState = true;
|
|
466
572
|
d.errorMsg = '设备处于休眠中';
|
|
@@ -472,50 +578,18 @@ const Player = props => {
|
|
|
472
578
|
});
|
|
473
579
|
} else if (playState.initLy && !privateState) {
|
|
474
580
|
ipcTTTOperatorLog("VID: privateState_status_change: ".concat(privateState));
|
|
475
|
-
|
|
581
|
+
if (isPreviewControlled) {
|
|
582
|
+
runPullStream();
|
|
583
|
+
} else {
|
|
584
|
+
retry();
|
|
585
|
+
}
|
|
476
586
|
} else if (playState.initLy && privateState) {
|
|
477
587
|
stopPreview();
|
|
478
588
|
// 如果隐私模式为true, 主动推一波流变化的状态码,适配ios不触发connectChange的情况
|
|
479
589
|
onChangeStreamStatus && onChangeStreamStatus(-1001);
|
|
480
590
|
}
|
|
481
591
|
}
|
|
482
|
-
}, [phoneNetworkConnect, onlineStatus, playState.initLy, privateState, limitFlow,
|
|
483
|
-
const retry = useMemoizedFn(() => {
|
|
484
|
-
console.log('重新拉流启动');
|
|
485
|
-
setAutoPlay(true);
|
|
486
|
-
// 任何重试拉流时, 将播放器状态还原为loading状态
|
|
487
|
-
setVideoErrCode('');
|
|
488
|
-
setPlayState(d => {
|
|
489
|
-
d.loadingState = true;
|
|
490
|
-
d.errorState = false;
|
|
491
|
-
d.errorMsg = '';
|
|
492
|
-
});
|
|
493
|
-
// 排除默认值为"",不等于播放器路由时, 不进行重试拉流
|
|
494
|
-
|
|
495
|
-
if (playerRoute !== '' && playerRoute !== getPlayerRoute()) {
|
|
496
|
-
console.log('不在播放器路由内, 不进行拉流');
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
if (isInBackgroundRef.current) {
|
|
500
|
-
console.log('处于后台/内存缓存,拦截拉流');
|
|
501
|
-
ipcTTTOperatorLog('VID: isInBackground, block retry');
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
phoneNetworkConnect && onlineStatus && privateState && (!isLowPowerDevice || isVirtualDevice) && handleReWakeCamera();
|
|
505
|
-
|
|
506
|
-
// 低功耗设备隐私模式需单独处理,先进行下发唤醒, 唤醒后再进行下发DP
|
|
507
|
-
phoneNetworkConnect && onlineStatus && privateState && isLowPowerDevice && !isVirtualDevice && handleReWakeCameraLowPowerDevice();
|
|
508
|
-
phoneNetworkConnect && onlineStatus && !privateState && _retry();
|
|
509
|
-
// }, [isLowPowerDevice, phoneNetworkConnect && playState.connectState, privateState, onlineStatus]);
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
// 创建ipc实例
|
|
513
|
-
const createIpcCtx = () => {
|
|
514
|
-
onCtx && onCtx({
|
|
515
|
-
ctx: ipcCtx.current,
|
|
516
|
-
retry
|
|
517
|
-
});
|
|
518
|
-
};
|
|
592
|
+
}, [phoneNetworkConnect, onlineStatus, playState.initLy, privateState, limitFlow, previewOn, isPreviewControlled, previewEnabled, runPullStream, retry]);
|
|
519
593
|
|
|
520
594
|
// 视图层准备就绪,开始建立连接
|
|
521
595
|
|
|
@@ -693,7 +767,7 @@ const Player = props => {
|
|
|
693
767
|
hideFeedBackButton: hideFeedBackButton,
|
|
694
768
|
isShare: isShare,
|
|
695
769
|
limitFlow: limitFlow,
|
|
696
|
-
autoPlay:
|
|
770
|
+
autoPlay: previewOn
|
|
697
771
|
}), /*#__PURE__*/React.createElement(FullScreenBackButton, {
|
|
698
772
|
isVisible: screenType === 'landscape' && (playState.loadingState || playState.errorState),
|
|
699
773
|
getClassName: getClassName,
|
package/lib/typings/index.d.ts
CHANGED
|
@@ -98,10 +98,14 @@ export type IProps = {
|
|
|
98
98
|
onCameraNotifyWeakNetwork?: (data) => void;
|
|
99
99
|
/**
|
|
100
100
|
* @description.en onCtx
|
|
101
|
-
* @description.zh 获取ipcPlayer实例ctx
|
|
101
|
+
* @description.zh 获取 ipcPlayer 实例 ctx、retry,以及 setPreviewEnabled(与 previewEnabled 受控配合或独立命令式开关拉流)
|
|
102
102
|
* @default (playerRef) => void
|
|
103
103
|
*/
|
|
104
|
-
onCtx?: (playerRef
|
|
104
|
+
onCtx?: (playerRef: {
|
|
105
|
+
ctx: any;
|
|
106
|
+
retry: () => void;
|
|
107
|
+
setPreviewEnabled: (enabled: boolean) => void;
|
|
108
|
+
}) => void;
|
|
105
109
|
/**
|
|
106
110
|
* @description.en onInitPreview
|
|
107
111
|
* @description.zh 初始化预览成功通知
|
|
@@ -217,15 +221,27 @@ export type IProps = {
|
|
|
217
221
|
*/
|
|
218
222
|
playerRoute?: string;
|
|
219
223
|
/**
|
|
220
|
-
* @description.en
|
|
221
|
-
* @description.zh
|
|
222
|
-
* @default
|
|
224
|
+
* @description.en Whether to pull preview. If omitted, treated as true (previewOn = previewEnabled ?? true). If passed, controlled mode (isPreviewControlled = true); pair with onPreviewEnabledChange for retry/lifecycle.
|
|
225
|
+
* @description.zh 是否拉流;未传等价 true;传入则为受控(与 onPreviewEnabledChange 配合)。
|
|
226
|
+
* @default undefined
|
|
227
|
+
*/
|
|
228
|
+
previewEnabled?: boolean;
|
|
229
|
+
/**
|
|
230
|
+
* @description.en Required for controlled previewEnabled when user retries or lifecycle syncs preview state
|
|
231
|
+
* @description.zh 传入 previewEnabled 受控时建议配置:重试开流、hide/pause 与父级状态同步依赖此回调
|
|
232
|
+
* @default undefined
|
|
223
233
|
*/
|
|
224
|
-
|
|
234
|
+
onPreviewEnabledChange?: (enabled: boolean) => void;
|
|
225
235
|
/**
|
|
226
236
|
* @description.en Limit flow for the player
|
|
227
237
|
* @description.zh 播放器是否限流
|
|
228
238
|
* @default false
|
|
229
239
|
*/
|
|
230
240
|
limitFlow?: boolean;
|
|
241
|
+
/**
|
|
242
|
+
* @description.en Auto wake up device on init (low power device only)
|
|
243
|
+
* @description.zh 初始化时是否自动唤醒设备(仅低功耗设备生效),需配合 defaultAutoPlay=false 使用实现"唤醒但不拉流"
|
|
244
|
+
* @default false
|
|
245
|
+
*/
|
|
246
|
+
autoWakeUp?: boolean;
|
|
231
247
|
};
|