代码如下:
choose audio file to get length: <input style="cursor: pointer;" type="file" id="file" multiple="multiple" /> <script> //when files are selected: $("#file").change(async function (e) { console.log('file(s) selected') //get files var files = e.currentTarget.files; //get number of files var numberOfFiles = files.length; //for each file for (i = 0; i < numberOfFiles; i++) { console.log(`songs[${i}].type=`, files[i].type) //get file length let songLength = await getSongLength(files[i]); console.log('songLength=', songLength) } }); //recieve audio file, return length function getSongLength(song) { return new Promise(function (resolve, reject) { console.log('getSongLength() begin setup') //create objectURL and audio object for ssong objectURL = URL.createObjectURL(song); mySound = new Audio([objectURL]) console.log('getSongLength() end setup') //when song metadata is loaded: mySound.addEventListener("canplaythrough", function (e) { console.log('getSongLength() canplaythrough') var seconds = e.currentTarget.duration; resolve(seconds) }); }); } </script>
原因
这是因为您的浏览器不支持Apple Lossless编解码器。如果您在Safari中尝试,则可以使用。
如果您将error事件附加到媒体元素,就会看到它触发了。
除了使用诸如mediainfo.js(2.4MB +)之类的笨重的机制,它应该支持大多数格式之外,没有真正的通用解决方案。
const input = document.querySelector( "input" ); input.onchange = async (evt) => { const mediainfo = await new Promise( (res) => MediaInfo(null, res) ); const file = input.files[ 0 ]; const getSize = () => file.size; const readChunk = async (chunkSize, offset) => new Uint8Array( await file.slice(offset, offset + chunkSize).arrayBuffer() ); const info = await mediainfo.analyzeData(getSize, readChunk); // assumes we are only interested in audio duration const audio_track = info.media.track.find( (track) => track[ "@type" ] === "Audio" ); console.log( audio_track.Duration ); };
<script src="https://unpkg.com/mediainfo.js@0.1.4/dist/mediainfo.min.js"></script> <input type="file">