如何将文件加载到HTML5音频标签中

6

如何将一个音频文件从 <input type="file"> 标签加载到音频标签中?我已经尝试了:

<input type="file" id="file"></input>
<script>
var file = document.getElementById("file");
var audio = document.createElement("audio");
audio.src = file.value;
document.write(audio)
</script>

所以你想通过文件输入选择一个文件,一旦选择完成就将其加载到音频标签中? - Shan Robertson
1
你可能需要先上传那个文件... 当使用文件输入选择时,你只能得到计算机上该文件的路径引用,即使你在本地设置中使用它,你的脚本也会按照其自己的根目录执行。输入所提供的数据只是一个路径。 - Shan Robertson
3个回答

8
我相信这将满足你的需求。首先,文件输入需要通过JavaScript或jQuery(如果您喜欢的话)绑定。您可以使用Blob 浏览器支持。以下是一个非常基本的示例;
<input type="file" id="file"></input>
<audio id="audio" controls autoplay></audio>

我们使用以下方式通过AddEventListener来绑定#file的变化。
// Check for BlobURL support
var blob = window.URL || window.webkitURL;
    if (!blob) {
        console.log('Your browser does not support Blob URLs :(');
        return;           
    }

document.getElementById('file').addEventListener('change', function(event){

        consolePrint('change on input#file triggered');
        var file = this.files[0],
         fileURL = blob.createObjectURL(file);
        console.log(file);
        console.log('File name: '+file.name);
        console.log('File type: '+file.type);
        console.log('File BlobURL: '+ fileURL);
        document.getElementById('audio').src = fileURL;

});

另一方面,这里有一个我创建的漂亮且更加交互式的示例

<iframe style="height:600px;width:102.7%;margin:-10px;overflow:hidden;" src="//jsfiddle.net/adamazad/0oy5moph/embedded/result,js,html,css/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>


0

    var wrap = document.getElementById("wrap");
    var file = document.getElementById("file");
    var audio = document.createElement("audio");
    file.onchange = function() {
        audio.src = file.value;
        wrap.appendChild(audio);
    };
<div id="wrap">
    <input type="file" id="file">
</div>

这是为了实现思路,但这也无法实现,因为上传的url不是本地url,您可以在评论区与我讨论。


我弄清楚了,我的做法是将音频文件转换为base64,然后将源设置为等于base64字符串。 - Mason Wright

0
我已经开发了一个es6代码,用一个能够捕获错误并在成功时解决的Promise来将文件加载到音频元素中。

    //functions:

    function setSrcObject(element, f) {
    if ('srcObject' in element) {
      try {
        // eslint-disable-next-line no-param-reassign
        element.srcObject = f; // this is the new way. only safary supports muliplt inputs, it is possible to put here media streams and files and blobs, but current new browsers support only media stream so need a fallback.
      } catch (e) {
        if (e.name !== 'TypeError') throw e;
        // Avoid using this in new browsers, as it is going away.
        // eslint-disable-next-line no-param-reassign
        element.src = URL.createObjectURL(f);
      }
    }
    // eslint-disable-next-line no-param-reassign
    else element.src = URL.createObjectURL(f);
  }

  function loadAudioFile(audio, file) {
    let onloadeddataResolve;
    let onloadeddataReject;
    // once
    function onloadeddataEv() {
      onloadeddataResolve();
      audio.removeEventListener('loadeddata', onloadeddataEv);
      audio.removeEventListener('error', onerrorEv);
    }
    function onerrorEv(e) {
      onloadeddataReject(e.srcElement.error);
      audio.removeEventListener('loadeddata', onloadeddataEv);
      audio.removeEventListener('error', onerrorEv);
    }
    audio.addEventListener('loadeddata', onloadeddataEv);
    audio.addEventListener('error', onerrorEv);
    const promise = new Promise((resolve, reject) => {
      onloadeddataResolve = resolve;
      onloadeddataReject = reject;
    }); // inversion of control promise
    // try load it:
    try {
      // audio.src =  url; // = http://example.org/myfile.mp3 or .ogg
      setSrcObject(audio, file);
      audio.load();
    } catch (e) {
      audio.removeEventListener('loadeddata', onloadeddataEv);
      audio.removeEventListener('error', onerrorEv);
      onloadeddataReject(e);
    }
    return promise;
  }

//example:

let audio =  new Audio(); // create audio element
audio.autoPlay=false;
filefield.oninput=async function test() {
  try {
    const f =  filefield.files[0]; // take first file 
    await loadAudioFile(audio, f); // load the file
    await audio.play();
  } catch(e) { console.log(e.stack?e.stack:e) }
}
playpause.onclick = async () => {  if( audio.paused) await audio.play(); else await audio.pause(); };
<input type="file" id="filefield" multiple="multiple"  accept="audio/mpeg, audio/mp4, audio/ogg">
<input id="playpause" value="play pause" type="button">

这个解决方案是我开发的播放列表对象的一部分

https://jsfiddle.net/shimondoodkin/7zmhsg30/20/

相关解决方案,使用Web音频API播放音频

https://jsfiddle.net/shimondoodkin/251wx8ys/31/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接