0

I'm trying create Audio sync with text. That's what I thought, but then I'm getting this error "Cannot read property audioPlayer of undefined". I would like to know how I can get this working.

Error message

<audio #audiofile src="/assets/song/test2f.mp3" controls></audio><br>
    <div id="subtitles"></div>
    
    import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-starter',
      templateUrl: './starter.component.html',
      styleUrls: ['./starter.component.scss']
    })
    
    /**
     * Utility starter component
     */
    export class StarterComponent implements OnInit, AfterViewInit {
      // bread crumb items
      breadCrumbItems: Array<{}>;
    
      @ViewChild('audiofile') audioPlayer: ElementRef<HTMLAudioElement> ;
    
      constructor() {}
    
      ngOnInit() {
        this.breadCrumbItems = [{ label: 'Utility' }, { label: 'Starter Page', active: true }];
      }
    
      ngAfterViewInit() {
        console.log(this.audioPlayer.nativeElement);
        this.just_one();
      }
    
      just_one() {
    
        var subtitles = document.getElementById("subtitles");
        var syncData = [
          { "end": "0.2","start": "0.0","text": "I"},
          { "end": "0.7000000000000001","start": "0.2","text": "believe"},
          { "end": "0.9","start": "0.7000000000000001","text": "you're"},
          { "end": "1.2","start": "0.9","text": "just"},
          { "end": "1.4","start": "1.2","text": "talking"} ,
          { "end": "1.7000000000000002","start": "1.4","text": "nonsense"}                   
        ];
    
        console.log(syncData)
        createSubtitle();
    
        function createSubtitle()
          {
            var element;
            for (var i = 0; i < syncData.length; i++) {
              element = document.createElement('span');
              element.setAttribute("id", "c_" + i);
              element.innerText = syncData[i].text + " ";
              subtitles.appendChild(element);
            }
          }
    
        this.audioPlayer.nativeElement.addEventListener("timeupdate", function(e) {
          syncData.forEach(function(element, index, array) {
            var currTime = this.audioPlayer.nativeElement.currentTime;
            console.log(currTime)
          });
        });
      }
      
    }
0

2 Answers 2

1

In your createSubtitle() function you use syncData.forEach() Try converting you function declaration in the forEach callback to an arrow function

Sign up to request clarification or add additional context in comments.

Comments

0

That's because you are using the function keyword to create a callback function, and not the arrow function. You are losing the this context this way. There are plenty of questions about this, but very difficult to look for, because everybody experience this problem in a different way. Basically, never use the function keyword inside a class:

this.audioPlayer.nativeElement.addEventListener("timeupdate", (e) => {
  syncData.forEach((element, index, array) => {
    var currTime = this.audioPlayer.nativeElement.currentTime;
    console.log(currTime)
  });
});

However, you might be better of using the angular event binding:

<audio #audiofile src="/assets/song/test2f.mp3" controls (timeupdate)="onTimeUpdate(e)">

onTimeUpdate(event): void {
  this.syncData.forEach((element, index, array) => {
    const currTime = (event.target as HTMLAudioElement).currentTime;
    console.log(currTime);
  });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.