@galacean/effects-plugin-multimedia 2.6.6 → 2.7.0-alpha.0

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.
@@ -1,9 +1,12 @@
1
1
  import { RendererComponent, spec } from '@galacean/effects';
2
2
  import { AudioPlayer } from './audio-player';
3
+ /**
4
+ * Audio component class
5
+ */
3
6
  export declare class AudioComponent extends RendererComponent {
4
7
  audioPlayer: AudioPlayer;
5
- private isVideoPlay;
6
- private threshold;
8
+ private isPlaying;
9
+ onAwake(): void;
7
10
  onUpdate(dt: number): void;
8
11
  fromData(data: spec.AudioComponentData): void;
9
12
  /**
@@ -13,6 +13,7 @@ export declare class AudioPlayer {
13
13
  private engine;
14
14
  audio?: HTMLAudioElement;
15
15
  audioSourceInfo: AudioSourceInfo;
16
+ private pendingOffset;
16
17
  private isSupportAudioContext;
17
18
  private options;
18
19
  private destroyed;
@@ -26,6 +27,15 @@ export declare class AudioPlayer {
26
27
  */
27
28
  setAudioSource(audio: AudioBuffer | HTMLAudioElement): void;
28
29
  getCurrentTime(): number;
30
+ /**
31
+ * 设置音频当前时间
32
+ * WebAudio下设置 this.pendingOffset,后面play时直接从该事件play
33
+ * HTMLAudioElement下直接设置时间
34
+ */
35
+ setCurrentTime(time: number): void;
36
+ /**
37
+ * 播放音频
38
+ */
29
39
  play(): void;
30
40
  pause(): void;
31
41
  setVolume(volume: number): void;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Description: Galacean Effects player multimedia plugin
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 云垣
6
- * Version: v2.6.6
6
+ * Version: v2.7.0-alpha.0
7
7
  */
8
8
 
9
9
  'use strict';
@@ -502,11 +502,11 @@ var MultimediaError = /*#__PURE__*/ function(Error1) {
502
502
  }(EFFECTS.AbstractPlugin);
503
503
 
504
504
  var seed = 0;
505
- exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
506
- _inherits(VideoComponent, BaseRenderComponent);
505
+ exports.VideoComponent = /*#__PURE__*/ function(MaskableGraphic) {
506
+ _inherits(VideoComponent, MaskableGraphic);
507
507
  function VideoComponent(engine) {
508
508
  var _this;
509
- _this = BaseRenderComponent.call(this, engine) || this;
509
+ _this = MaskableGraphic.call(this, engine) || this;
510
510
  _this.threshold = 0.03;
511
511
  /**
512
512
  * 播放标志位
@@ -582,27 +582,16 @@ exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
582
582
  _proto.onAwake = function onAwake() {
583
583
  var _this = this;
584
584
  var _this_item_composition, _this_item_composition1;
585
- BaseRenderComponent.prototype.onAwake.call(this);
585
+ MaskableGraphic.prototype.onAwake.call(this);
586
586
  (_this_item_composition = this.item.composition) == null ? void 0 : _this_item_composition.on("goto", function(option) {
587
- if (option.time > 0) {
588
- var _this_item = _this.item, endBehavior = _this_item.endBehavior, start = _this_item.start, duration = _this_item.duration;
589
- if (endBehavior === EFFECTS.spec.EndBehavior.freeze || endBehavior === EFFECTS.spec.EndBehavior.restart) {
590
- _this.setCurrentTime((option.time - start) % duration);
591
- } else {
592
- if (option.time >= duration) {
593
- _this.onDisable();
594
- } else {
595
- _this.setCurrentTime(option.time - start);
596
- }
597
- }
598
- }
587
+ _this.setCurrentTime(_this.item.time);
599
588
  });
600
589
  (_this_item_composition1 = this.item.composition) == null ? void 0 : _this_item_composition1.on("pause", function() {
601
590
  _this.pauseVideo();
602
591
  });
603
592
  };
604
593
  _proto.fromData = function fromData(data) {
605
- BaseRenderComponent.prototype.fromData.call(this, data);
594
+ MaskableGraphic.prototype.fromData.call(this, data);
606
595
  var interaction = data.interaction, options = data.options;
607
596
  var video = options.video, _options_startColor = options.startColor, startColor = _options_startColor === void 0 ? [
608
597
  1,
@@ -635,20 +624,21 @@ exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
635
624
  this.material.setColor("_Color", new EFFECTS.math.Color().setFromArray(startColor));
636
625
  };
637
626
  _proto.render = function render(renderer) {
638
- BaseRenderComponent.prototype.render.call(this, renderer);
627
+ MaskableGraphic.prototype.render.call(this, renderer);
639
628
  this.renderer.texture.uploadCurrentVideoFrame();
640
629
  };
641
630
  _proto.onUpdate = function onUpdate(dt) {
642
- BaseRenderComponent.prototype.onUpdate.call(this, dt);
643
- var _this_item = this.item, time = _this_item.time, duration = _this_item.duration, endBehavior = _this_item.endBehavior, composition = _this_item.composition, start = _this_item.start;
631
+ MaskableGraphic.prototype.onUpdate.call(this, dt);
632
+ var _this_item = this.item, time = _this_item.time, duration = _this_item.duration, endBehavior = _this_item.endBehavior, composition = _this_item.composition;
644
633
  EFFECTS.assertExist(composition);
645
634
  var _composition_rootItem = composition.rootItem, rootEndBehavior = _composition_rootItem.endBehavior, rootDuration = _composition_rootItem.duration;
646
- var isEnd = time === 0 || time === rootDuration - start || Math.abs(rootDuration - duration - time) < 1e-10 || Math.abs(time - duration) < this.threshold;
635
+ var isEnd = time === 0 || time === rootDuration || Math.abs(rootDuration - duration - time) < 1e-10 || Math.abs(time - duration) < this.threshold;
647
636
  if (time > 0 && !isEnd) {
648
637
  this.setVisible(true);
649
638
  this.playVideo();
650
639
  }
651
- if (time === 0 || time === rootDuration - start || Math.abs(rootDuration - duration - time) < 1e-10) {
640
+ this.renderer.texture.uploadCurrentVideoFrame();
641
+ if (time === 0 || time === rootDuration || Math.abs(rootDuration - duration - time) < 1e-10) {
652
642
  if (rootEndBehavior === EFFECTS.spec.EndBehavior.freeze) {
653
643
  var _this_video;
654
644
  if (!((_this_video = this.video) == null ? void 0 : _this_video.paused)) {
@@ -777,7 +767,7 @@ exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
777
767
  this.video.pause();
778
768
  };
779
769
  _proto.onDestroy = function onDestroy() {
780
- BaseRenderComponent.prototype.onDestroy.call(this);
770
+ MaskableGraphic.prototype.onDestroy.call(this);
781
771
  this.played = false;
782
772
  this.isPlayLoading = false;
783
773
  this.pendingPause = false;
@@ -789,7 +779,7 @@ exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
789
779
  };
790
780
  _proto.onDisable = function onDisable() {
791
781
  var _this_item;
792
- BaseRenderComponent.prototype.onDisable.call(this);
782
+ MaskableGraphic.prototype.onDisable.call(this);
793
783
  this.isVideoActive = false;
794
784
  this.pauseVideo();
795
785
  var endBehavior = (_this_item = this.item) == null ? void 0 : _this_item.endBehavior;
@@ -798,12 +788,12 @@ exports.VideoComponent = /*#__PURE__*/ function(BaseRenderComponent) {
798
788
  }
799
789
  };
800
790
  _proto.onEnable = function onEnable() {
801
- BaseRenderComponent.prototype.onEnable.call(this);
791
+ MaskableGraphic.prototype.onEnable.call(this);
802
792
  this.isVideoActive = true;
803
793
  this.playVideo();
804
794
  };
805
795
  return VideoComponent;
806
- }(EFFECTS.BaseRenderComponent);
796
+ }(EFFECTS.MaskableGraphic);
807
797
  exports.VideoComponent = __decorate([
808
798
  EFFECTS.effectsClass(EFFECTS.spec.DataType.VideoComponent)
809
799
  ], exports.VideoComponent);
@@ -812,6 +802,7 @@ var AudioPlayer = /*#__PURE__*/ function() {
812
802
  function AudioPlayer(engine, audio) {
813
803
  this.engine = engine;
814
804
  this.audioSourceInfo = {};
805
+ this.pendingOffset = 0;
815
806
  this.isSupportAudioContext = !!window["AudioContext"];
816
807
  this.options = {
817
808
  endBehavior: EFFECTS.spec.EndBehavior.destroy,
@@ -861,30 +852,83 @@ var AudioPlayer = /*#__PURE__*/ function() {
861
852
  return ((_this_audio = this.audio) == null ? void 0 : _this_audio.currentTime) || 0;
862
853
  }
863
854
  };
864
- _proto.play = function play() {
855
+ /**
856
+ * 设置音频当前时间
857
+ * WebAudio下设置 this.pendingOffset,后面play时直接从该事件play
858
+ * HTMLAudioElement下直接设置时间
859
+ */ _proto.setCurrentTime = function setCurrentTime(time) {
860
+ var t = Math.max(0, time);
861
+ if (this.isSupportAudioContext) {
862
+ var upper = this.options.duration && this.options.duration > 0 ? this.options.duration : undefined;
863
+ this.pendingOffset = upper ? Math.min(t, upper) : t;
864
+ return;
865
+ } else {
866
+ if (this.audio) {
867
+ var dur = Number.isFinite(this.audio.duration) ? this.audio.duration : undefined;
868
+ var clamped = dur ? Math.min(t, dur) : t;
869
+ this.audio.currentTime = clamped;
870
+ }
871
+ }
872
+ };
873
+ /**
874
+ * 播放音频
875
+ */ _proto.play = function play() {
865
876
  var _this = this;
866
877
  if (this.isSupportAudioContext) {
867
- var _this_audioSourceInfo = this.audioSourceInfo, audioContext = _this_audioSourceInfo.audioContext, source = _this_audioSourceInfo.source;
868
- if (source && audioContext) {
869
- switch(this.options.endBehavior){
870
- case EFFECTS.spec.EndBehavior.destroy:
871
- case EFFECTS.spec.EndBehavior.freeze:
872
- source.start(0);
873
- break;
874
- case EFFECTS.spec.EndBehavior.restart:
875
- source.loop = true;
876
- source.loopStart = 0;
877
- source.loopEnd = this.options.duration;
878
- source.start(0);
879
- break;
880
- }
878
+ var _this_audioSourceInfo = this.audioSourceInfo, audioContext = _this_audioSourceInfo.audioContext, source = _this_audioSourceInfo.source, gainNode = _this_audioSourceInfo.gainNode;
879
+ if (!audioContext || !gainNode) {
880
+ return;
881
+ }
882
+ var buffer = source == null ? void 0 : source.buffer;
883
+ if (!buffer) {
884
+ return;
885
+ }
886
+ var maxDuration = this.options.duration && this.options.duration > 0 ? this.options.duration : buffer.duration;
887
+ // 保险起见,先停掉旧 source,吞掉异常(旧节点是否成功 stop 不影响后续逻辑)
888
+ // eslint-disable-next-line no-empty
889
+ try {
890
+ source == null ? void 0 : source.stop();
891
+ } catch (e) {}
892
+ // AudioBufferSourceNode 是一次性节点,start 后不能二次 start。无论之前是否 start 过,先调用 stop 清理旧节点。
893
+ var newSource = audioContext.createBufferSource();
894
+ newSource.buffer = buffer;
895
+ newSource.connect(gainNode);
896
+ var _source_playbackRate_value;
897
+ // 继承旧的播放参数
898
+ newSource.playbackRate.value = (_source_playbackRate_value = source == null ? void 0 : source.playbackRate.value) != null ? _source_playbackRate_value : 1;
899
+ if (this.options.endBehavior === EFFECTS.spec.EndBehavior.restart) {
900
+ newSource.loop = true;
901
+ newSource.loopStart = 0;
902
+ newSource.loopEnd = maxDuration;
903
+ } else {
904
+ var _source_loop;
905
+ newSource.loop = (_source_loop = source == null ? void 0 : source.loop) != null ? _source_loop : false;
906
+ var _source_loopStart;
907
+ newSource.loopStart = (_source_loopStart = source == null ? void 0 : source.loopStart) != null ? _source_loopStart : 0;
908
+ var _source_loopEnd;
909
+ newSource.loopEnd = (_source_loopEnd = source == null ? void 0 : source.loopEnd) != null ? _source_loopEnd : maxDuration;
910
+ }
911
+ this.audioSourceInfo.source = newSource;
912
+ if (audioContext.state === "suspended") {
913
+ audioContext.resume().catch(function(e) {
914
+ return _this.engine.renderErrors.add(e);
915
+ });
916
+ }
917
+ try {
918
+ newSource.start(0, this.pendingOffset || 0);
919
+ this.pendingOffset = 0;
920
+ this.started = true;
921
+ } catch (e) {
922
+ this.engine.renderErrors.add(e);
881
923
  }
882
- this.started = true;
883
924
  } else {
884
- var _this_audio;
885
- (_this_audio = this.audio) == null ? void 0 : _this_audio.play().catch(function(e) {
886
- _this.engine.renderErrors.add(e);
887
- });
925
+ if (this.audio) {
926
+ this.audio.loop = this.options.endBehavior === EFFECTS.spec.EndBehavior.restart;
927
+ this.audio.play().catch(function(e) {
928
+ return _this.engine.renderErrors.add(e);
929
+ });
930
+ this.started = true;
931
+ }
888
932
  }
889
933
  };
890
934
  _proto.pause = function pause() {
@@ -988,27 +1032,41 @@ exports.AudioComponent = /*#__PURE__*/ function(RendererComponent) {
988
1032
  function AudioComponent() {
989
1033
  var _this;
990
1034
  _this = RendererComponent.apply(this, arguments) || this;
991
- _this.isVideoPlay = false;
992
- _this.threshold = 0.03;
1035
+ _this.isPlaying = false;
993
1036
  return _this;
994
1037
  }
995
1038
  var _proto = AudioComponent.prototype;
1039
+ _proto.onAwake = function onAwake() {
1040
+ var _this = this;
1041
+ var _this_item_composition, _this_item_composition1, _this_item_composition2;
1042
+ RendererComponent.prototype.onAwake.call(this);
1043
+ (_this_item_composition = this.item.composition) == null ? void 0 : _this_item_composition.on("play", function(option) {
1044
+ if (_this.item.time <= 0) {
1045
+ return;
1046
+ }
1047
+ _this.audioPlayer.setCurrentTime(_this.item.time);
1048
+ _this.audioPlayer.play();
1049
+ _this.isPlaying = true;
1050
+ });
1051
+ (_this_item_composition1 = this.item.composition) == null ? void 0 : _this_item_composition1.on("pause", function() {
1052
+ _this.audioPlayer.pause();
1053
+ _this.isPlaying = false;
1054
+ });
1055
+ (_this_item_composition2 = this.item.composition) == null ? void 0 : _this_item_composition2.on("goto", function(option) {
1056
+ _this.audioPlayer.setCurrentTime(_this.item.time);
1057
+ });
1058
+ };
996
1059
  _proto.onUpdate = function onUpdate(dt) {
997
1060
  RendererComponent.prototype.onUpdate.call(this, dt);
998
1061
  var _this_item = this.item, time = _this_item.time, duration = _this_item.duration, endBehavior = _this_item.endBehavior;
1062
+ if (time > 0 && this.isPlaying == false) {
1063
+ this.audioPlayer.play();
1064
+ this.isPlaying = true;
1065
+ }
999
1066
  this.audioPlayer.setOptions({
1000
1067
  duration: duration,
1001
1068
  endBehavior: endBehavior
1002
1069
  });
1003
- if (time >= 0 && !this.isVideoPlay) {
1004
- this.audioPlayer.play();
1005
- this.isVideoPlay = true;
1006
- }
1007
- if (Math.abs(time - duration) < this.threshold) {
1008
- if (endBehavior === EFFECTS.spec.EndBehavior.destroy) {
1009
- this.audioPlayer.pause();
1010
- }
1011
- }
1012
1070
  };
1013
1071
  _proto.fromData = function fromData(data) {
1014
1072
  RendererComponent.prototype.fromData.call(this, data);
@@ -1076,7 +1134,7 @@ exports.AudioComponent = __decorate([
1076
1134
 
1077
1135
  /**
1078
1136
  * 插件版本号
1079
- */ var version = "2.6.6";
1137
+ */ var version = "2.7.0-alpha.0";
1080
1138
  EFFECTS.registerPlugin("video", VideoLoader, EFFECTS.VFXItem);
1081
1139
  EFFECTS.registerPlugin("audio", AudioLoader, EFFECTS.VFXItem);
1082
1140
  EFFECTS.logger.info("Plugin multimedia version: " + version + ".");