javascriptangularblobhttpresponsearraybuffer

Blob could not be loaded from a localhost as src blob:


I'm having some trouble loading an audio file in WAV format returned from the backend as a Blob in Angular.

I have in my services the following:

getFileBlob(uniformName: string, path: string) {
    const currentPath = path.replace(/\\/g, '/');
    return this.http.get(`${environment.api_url}/content/v1.4/${currentPath}/${uniformName}/_blob`, { responseType: 'blob' });
  }

Where in my Angular component, I have the following:

this.dService.getFileBlob().subscribe((response: Blob) => {
        const url = URL.createObjectURL(response);
        this.type.set(response.type);
        this.src.set(url);
      });

I have the correct mapping in my audio source tag: [screenshot from the inspect1

In my template, I have:

<audio #media [vgMedia]="$any(media)" id="myAudio" preload="{{ preload }}" crossorigin>
      <source src="{{ src() }}" type="{{ type() }}">
      <track
      src="assets/data/Downloaded_transcriptVVV.vtt"
      kind="metadata"
      label="Cue Points"
      default
      #metadataTrack
    />
  </audio>

When I paste the blob in the browser, I get the file downloaded - (blob:http://localhost:4200/7071f3e7-9738-4ad7-b08f-67ddb5852c53) The problem is that the native HTML audio does not play at all. One important note is that I'm using Angular in a zoneless mode. If, however, I put a direct relative URL in the place of the src, it works:

`this.src.set('/assets/audio/E_2024-10-07_H_100748_060.wav')

I would highly appreciate anyone's advice on what I'm doing wrong.


Solution

  • The issue is that the audio player is loaded without a source. The player doesn't listen for new or changed sources and is therefore unaware of the added audio. The fix is to use audio.load(), which forces the browser to recheck the sources and notice the now added audio.

    The example below demonstrates that the browser doesn't play the audio if the src is set dynamically.

    const source = document.querySelector('source');
    const audio = document.querySelector('audio');
    
    fetch('https://upload.wikimedia.org/wikipedia/commons/3/3d/Alcal%C3%A1_de_Henares_%28RPS_13-04-2024%29_canto_de_ruise%C3%B1or_%28Luscinia_megarhynchos%29_en_el_Soto_del_Henares.wav')
      .then(res => res.blob())
      .then(blob => {
        const url = URL.createObjectURL(blob);
    
        source.type = blob.type;
        source.src = url;
      })
    <audio id="myAudio" preload="auto" crossorigin controls>
        <source />
    </audio>

    The fix is to use audio.load() to reset the player and force it to recheck the sources.

    const source = document.querySelector('source');
    const audio = document.querySelector('audio');
    
    fetch('https://upload.wikimedia.org/wikipedia/commons/3/3d/Alcal%C3%A1_de_Henares_%28RPS_13-04-2024%29_canto_de_ruise%C3%B1or_%28Luscinia_megarhynchos%29_en_el_Soto_del_Henares.wav')
      .then(res => res.blob())
      .then(blob => {
        const url = URL.createObjectURL(blob);
    
        source.type = blob.type;
        source.src = url;
    
        // add this line
        audio.load();
      })
    <audio id="myAudio" preload="auto" crossorigin controls>
        <source />
    </audio>