@realsee/vreo 2.6.2 → 2.6.4-alpha.1

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.
@@ -45,6 +45,11 @@ export declare class Controller extends Subscribe<VreoKeyframeEvent> {
45
45
  waveAppearance: WaveAppearance | null;
46
46
  appearance: Appearance;
47
47
  avatar: VreoVideo['avatar'];
48
+ /**
49
+ * 是否正在等待背景音乐加载
50
+ * 当此状态为 true 时,播放流程会暂停,等待音频加载完成
51
+ */
52
+ waitingForBgMusic: boolean;
48
53
  visible: boolean;
49
54
  /**
50
55
  * 获取当前播放媒体的类型
@@ -92,6 +97,11 @@ export declare class Controller extends Subscribe<VreoKeyframeEvent> {
92
97
  * @param ended - 是否已结束
93
98
  */
94
99
  setEnded(ended: boolean): void;
100
+ /**
101
+ * 设置是否正在等待背景音乐加载
102
+ * @param waiting - 是否正在等待
103
+ */
104
+ setWaitingForBgMusic(waiting: boolean): void;
95
105
  /**
96
106
  * 设置播放器外观
97
107
  * @param appearance - 外观配置对象
@@ -70,6 +70,7 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
70
70
  waveStyle: 'wave'
71
71
  });
72
72
  _defineProperty(_assertThisInitialized(_this), "avatar", {});
73
+ _defineProperty(_assertThisInitialized(_this), "waitingForBgMusic", false);
73
74
  _defineProperty(_assertThisInitialized(_this), "visible", false);
74
75
  _defineProperty(_assertThisInitialized(_this), "popUp", null);
75
76
  _defineProperty(_assertThisInitialized(_this), "drawerConfig", null);
@@ -99,7 +100,9 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
99
100
  setAppearance: action,
100
101
  configs: observable.ref,
101
102
  setEnded: action,
102
- setAvatar: action
103
+ setAvatar: action,
104
+ waitingForBgMusic: observable,
105
+ setWaitingForBgMusic: action
103
106
  });
104
107
  reaction(function () {
105
108
  return [_this.appearance.waveStyle, _this.loading];
@@ -192,6 +195,11 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
192
195
  get:
193
196
  // null 表示加载失败
194
197
 
198
+ /**
199
+ * 是否正在等待背景音乐加载
200
+ * 当此状态为 true 时,播放流程会暂停,等待音频加载完成
201
+ */
202
+
195
203
  /**
196
204
  * 获取当前播放媒体的类型
197
205
  * @returns 'video' | 'avatar' | 'none' - 媒体类型
@@ -282,6 +290,16 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
282
290
  this.ended = ended;
283
291
  }
284
292
 
293
+ /**
294
+ * 设置是否正在等待背景音乐加载
295
+ * @param waiting - 是否正在等待
296
+ */
297
+ }, {
298
+ key: "setWaitingForBgMusic",
299
+ value: function setWaitingForBgMusic(waiting) {
300
+ this.waitingForBgMusic = waiting;
301
+ }
302
+
285
303
  /**
286
304
  * 设置播放器外观
287
305
  * @param appearance - 外观配置对象
@@ -370,10 +388,19 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
370
388
  }, {
371
389
  key: "requestAnimationFrameLoop",
372
390
  value: function requestAnimationFrameLoop(callback) {
373
- var _this$mediaInstance,
374
- _this$mediaInstance4,
391
+ var _this$mediaInstance3,
392
+ _this$mediaInstance6,
375
393
  _this3 = this;
376
- if ((_this$mediaInstance = this.mediaInstance) !== null && _this$mediaInstance !== void 0 && _this$mediaInstance.ended && this.mediaInstance.currentTime !== 0) {
394
+ // 如果正在等待背景音乐加载,暂停整个播放流程
395
+ if (this.waitingForBgMusic) {
396
+ var _this$mediaInstance;
397
+ if (!((_this$mediaInstance = this.mediaInstance) !== null && _this$mediaInstance !== void 0 && _this$mediaInstance.paused)) {
398
+ var _this$mediaInstance2;
399
+ (_this$mediaInstance2 = this.mediaInstance) === null || _this$mediaInstance2 === void 0 ? void 0 : _this$mediaInstance2.pause();
400
+ }
401
+ return;
402
+ }
403
+ if ((_this$mediaInstance3 = this.mediaInstance) !== null && _this$mediaInstance3 !== void 0 && _this$mediaInstance3.ended && this.mediaInstance.currentTime !== 0) {
377
404
  var _this$vreoUnit;
378
405
  if (this.ended) return;
379
406
  (_this$vreoUnit = this.vreoUnit) === null || _this$vreoUnit === void 0 ? void 0 : _this$vreoUnit.keyframes.forEach(function (keyframe) {
@@ -386,14 +413,14 @@ export var Controller = /*#__PURE__*/function (_Subscribe) {
386
413
  return;
387
414
  }
388
415
  if (!this.playing) {
389
- var _this$mediaInstance2;
390
- if (!((_this$mediaInstance2 = this.mediaInstance) !== null && _this$mediaInstance2 !== void 0 && _this$mediaInstance2.paused)) {
391
- var _this$mediaInstance3;
392
- (_this$mediaInstance3 = this.mediaInstance) === null || _this$mediaInstance3 === void 0 ? void 0 : _this$mediaInstance3.pause();
416
+ var _this$mediaInstance4;
417
+ if (!((_this$mediaInstance4 = this.mediaInstance) !== null && _this$mediaInstance4 !== void 0 && _this$mediaInstance4.paused)) {
418
+ var _this$mediaInstance5;
419
+ (_this$mediaInstance5 = this.mediaInstance) === null || _this$mediaInstance5 === void 0 ? void 0 : _this$mediaInstance5.pause();
393
420
  }
394
421
  return;
395
422
  }
396
- if ((_this$mediaInstance4 = this.mediaInstance) !== null && _this$mediaInstance4 !== void 0 && _this$mediaInstance4.paused && this.playing) {
423
+ if ((_this$mediaInstance6 = this.mediaInstance) !== null && _this$mediaInstance6 !== void 0 && _this$mediaInstance6.paused && this.playing) {
397
424
  this.mediaInstance.play();
398
425
  }
399
426
  var currentKeyframes = this.currentKeyframes;
@@ -9,7 +9,8 @@ export function BgMusic() {
9
9
  React.useEffect(function () {
10
10
  var callback = /*#__PURE__*/function () {
11
11
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(keyframe, currentTime) {
12
- var start, end, _currentTime, audio, cleanAudio, play;
12
+ var _controller$configs$w, _controller$configs;
13
+ var start, end, _currentTime, audio, waitForLoaded, cleanAudio, play, playOnCanPlay;
13
14
  return _regeneratorRuntime.wrap(function _callee$(_context) {
14
15
  while (1) {
15
16
  switch (_context.prev = _context.next) {
@@ -24,32 +25,51 @@ export function BgMusic() {
24
25
  case 4:
25
26
  audio = getAudio(keyframe.data.url);
26
27
  audio.currentTime = Math.max(0, _currentTime);
27
- // console.log('play', audio.src)
28
- // const play = () => audio.play()
29
-
30
- audio.play();
28
+ waitForLoaded = (_controller$configs$w = (_controller$configs = controller.configs) === null || _controller$configs === void 0 ? void 0 : _controller$configs.waitForBgMusicLoaded) !== null && _controller$configs$w !== void 0 ? _controller$configs$w : false;
31
29
  cleanAudio = function cleanAudio() {
32
- // audio.removeEventListener('canplaythrough', play)
30
+ audio.removeEventListener('canplay', playOnCanPlay);
33
31
  audio.removeEventListener('pause', play);
34
32
  audio.pause();
35
33
  audio.src = '';
36
- // cleanTimeout()
37
- }; // audio.addEventListener('canplaythrough', play)
38
-
39
- audio.addEventListener('ended', function () {
40
- cleanAudio();
41
- });
34
+ };
42
35
  play = function play() {
43
36
  if (audio.realSrc === keyframe.data.url) {
44
37
  // 有可能会被其他音轨打断
45
38
  audio.play();
46
39
  }
40
+ }; // canplay 事件比 canplaythrough 更早触发,表示可以开始播放了
41
+ playOnCanPlay = function playOnCanPlay() {
42
+ audio.removeEventListener('canplay', playOnCanPlay);
43
+ audio.play();
44
+ // 解除等待状态,恢复主时间线播放
45
+ controller.setWaitingForBgMusic(false);
47
46
  };
47
+ if (waitForLoaded) {
48
+ // 等待音频加载完成后再播放
49
+ // readyState: 0=HAVE_NOTHING, 1=HAVE_METADATA, 2=HAVE_CURRENT_DATA, 3=HAVE_FUTURE_DATA, 4=HAVE_ENOUGH_DATA
50
+ if (audio.readyState >= 3) {
51
+ // readyState >= 3 表示有足够数据开始播放
52
+ audio.play();
53
+ } else {
54
+ // 设置等待状态,阻塞整个播放流程
55
+ controller.setWaitingForBgMusic(true);
56
+ // 监听 canplay 事件(可以开始播放)
57
+ audio.addEventListener('canplay', playOnCanPlay);
58
+ }
59
+ } else {
60
+ // 默认行为:立即播放,边加载边播放
61
+ audio.play();
62
+ }
63
+ audio.addEventListener('ended', function () {
64
+ cleanAudio();
65
+ });
48
66
  audio.addEventListener('pause', play);
49
67
  controller.once('paused', function () {
68
+ // 如果播放器暂停,也要解除等待状态
69
+ controller.setWaitingForBgMusic(false);
50
70
  cleanAudio();
51
71
  });
52
- case 12:
72
+ case 14:
53
73
  case "end":
54
74
  return _context.stop();
55
75
  }
@@ -37,6 +37,13 @@ export interface PlayerConfigs {
37
37
  waveStaticPrefix?: string;
38
38
  onAvatarClick?: () => any;
39
39
  onWaveClick?: () => any;
40
+ /**
41
+ * 是否等待背景音乐加载完成后再播放
42
+ * - true: 等待音频完全可播放(canplaythrough)后再播放,确保不会卡顿
43
+ * - false: 立即播放,边加载边播放(默认行为)
44
+ * @default false
45
+ */
46
+ waitForBgMusicLoaded?: boolean;
40
47
  }
41
48
  export type AppSize = 'S' | 'M' | 'L' | 'XL';
42
49
  export type WaveAppearance = 'single' | 'double' | 'solid' | 'swap' | 'expand';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realsee/vreo",
3
- "version": "2.6.2",
3
+ "version": "2.6.4-alpha.1",
4
4
  "type": "module",
5
5
  "description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
6
6
  "keywords": [