Обнаружение изменений не работает, когда используется веб-аудио - PullRequest
0 голосов
/ 19 февраля 2019

Аналогично Обнаружение угловых изменений с помощью HTMLAudioElement , но его решение не работает для меня.

В моем угловом приложении я хочу воспроизводить короткие wav-файлы с использованием веб-аудио.Во время воспроизведения кнопка воспроизведения должна стать кнопкой остановки, а после окончания кнопка остановки снова станет кнопкой воспроизведения.Я сделал простой аудио сервис, который запускает наблюдаемое сразу после AudioBufferSourceNode.start(0), а также запускает наблюдаемое в AudioBufferSourceNode.onended.Я вижу в консоли, что событие запускается, но пользовательский интерфейс не меняется.Я сделал стек, демонстрирующий мою проблему https://stackblitz.com/edit/angular-x5ytjt - при фактическом использовании аудио API (флажок установлен) пользовательский интерфейс не обновляется, когда только запускается наблюдаемый (флажок снят) пользовательский интерфейс обновляется.

Как мне добиться обновления моего интерфейса в этом случае?

компонент:

@Component({
  selector: 'hello',
  template: `
  <input type="checkbox" [(ngModel)]="playReal">Real playback (vs. fake-events)<br>
  Currently {{playing?"playing":"stopped"}}
  <button type="button" *ngIf="!playing" (click)="play()">play</button>
  <button type="button" *ngIf="playing" (click)="stop()">stop</button>

  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
  @Input() name: string;

  playing: boolean = false;
  subscription: Subscription;

  playReal: boolean = true;

  constructor(public audio: AudioService, public dataSvc: DataService, private ref: ChangeDetectorRef) { }

  ngOnInit() {
    this.subscription = this.audio.playing$.subscribe(value => {
      this.playing = value;
      console.debug('observer has fired. new value: ', value);
      // solution from /9955558/obnaruzhenie-uglovyh-izmenenii-s-pomoschy-htmlaudioelement
      this.ref.markForCheck();
    });

  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }


  play() {
    this.dataSvc.getAudio().subscribe(
      data => {
        if (this.playReal) {
          // do real playback
          this.audio.playBlob(data);
        } else {
          // only fake playing (tell the audio service to emit the event)
          this.audio.hackSetPlaying(true);
        }
      }
    )
  }

  stop() {
    if (this.playReal) {
      this.audio.stopPlay();
    } else {
      this.audio.hackSetPlaying(false);
    }
  }

}

аудиосервис:

public playBlob( data: Blob ) {
        // playBlob and play inspired by https://stackoverflow.com/questions/24151121/how-to-play-wav-audio-byte-array-via-javascript-html5

        // create audio context if necessary
        if (!this.audioCtx) {
            this.audioCtx = new AudioContext();
        }

        // use file reader to convert blob to ArrayBuffer
        let fr: FileReader = new FileReader();

        fr.onload = () => {
            // after loading decode and play the wav file
            this.audioCtx.decodeAudioData(<ArrayBuffer>fr.result, (res) => {this.play(res);});
        }

        fr.readAsArrayBuffer(data);
    }

    private play(audioBuff: AudioBuffer) {
        if (!this.audioSrc) {
            this.audioSrc = this.audioCtx.createBufferSource();
        }
        this.audioSrc.buffer = audioBuff;
        this.audioSrc.connect(this.audioCtx.destination);
        this.audioSrc.start(0);
        this.playing = true;
        this.playingSubject.next(this.playing);
        console.debug('audioService has set playing to true');
        this.audioSrc.onended = () => {
            this.playing = false;
            this.playingSubject.next(this.playing);
            console.debug('audioService set playing to false');
            this.audioSrc = null; // audioSrc can only be used once
        }
    }  

Редактировать: я простоузнал, что то, что я использую, по-видимому, называется web audio api, а не html5 audio.Исправленные теги, заголовок и т. Д.

1 Ответ

0 голосов
/ 07 марта 2019

Я нашел ответ в https://stackoverflow.com/a/46866433/2131459

Мне нужно вызвать ChangeDetectorRef метод detectChanges() вместо markForCheck().Я обновил стек стека.

...