如何获取 JavaScript 中创建的音频元素的文件大小?

How can I get the file size of a created audio element in JavaScript?

如何获取非DOM创建的音频元素的文件大小?

我想我可以使用 HTML5 文件 API – 根据 Client Checking file size using HTML5? – 但它似乎不适用于不在 DOM 中的元素.

我在下面创建了一个示例 – 请参阅行 console.log(audio_file.files[0].size);,它给出了一个错误:

TypeError: audio_file.files is undefined

// Create a non-dom allocated Audio element
var audio_file = document.createElement('audio');

// Define the URL of the MP3 audio file
audio_file.src = "https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3";

// Once the metadata has been loaded, display the duration in the console
audio_file.addEventListener('loadedmetadata', function(){
    // Obtain the duration in seconds of the audio file
    var duration = audio_file.duration;
    
    const duration_hhmmss = new Date(duration * 1000).toISOString().substr(11, 8);

    console.log("The duration of the song is of: " + duration_hhmmss);
    console.log(audio_file.files[0].size);
},false);

我尝试进行 fetch 调用并从 blob 计算文件的大小。

但缺点是,在文件完全加载之前我们无法知道文件的大小,因为给定 mp3 url 的响应 headers 没有任何与大小相关的信息。

这里我设置了获取到音频元素后的音频数据,但这不是必须的。我只是添加它来播放音频文件。

(按下 运行 代码片段 后,您必须等到文件加载后才能看到结果。)

const audioEl = document.querySelector('audio');

fetch(
  "https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"
)
  .then((response) => {
    // console.log(response);
    return response.body
  })
  .then((data) => {
    var reader = data.getReader();
    return new ReadableStream({
      start(controller) {
        return pump();
        function pump() {
          return reader.read().then(({ done, value }) => {
            // When no more data needs to be consumed, close the stream
            if (done) {
              controller.close();
              return;
            }
            // Enqueue the next data chunk into our target stream
            controller.enqueue(value);
            return pump();
          });
        }
      }
    });
  })
  .then((stream) => new Response(stream, {headers: {'Content-Type': 'audio/mpeg'}}))
  .then((response) => response.blob())
  .then(blob => {
    // console.log(blob);
    const reader = new FileReader();
    reader.addEventListener('loadend', () => {
       audioEl.src = reader.result; // output of reader.readAsDataURL
    });
    reader.readAsDataURL(blob);

    const sizeInByte = blob.size;
    const sizeInMB = sizeInByte / 1024 / 1024;
    document.querySelector('#size').innerText = `Size of the loaded audio is ${sizeInMB.toFixed(2)}MB`;
  });
<audio controls></audio>
<div id="size"></div>