马黑黑 发表于 2022-12-8 19:49

获取本地音频波形数据(定稿)

本帖最后由 马黑黑 于 2022-12-16 13:22 编辑 <br /><br /><style>
#papa { margin: 0 0 0 calc(50% - 481px); padding: 10px; width: 800px; background: linear-gradient(to bottom right,#000,#ffc); box-shadow: 3px 6px 20px #000; border-radius: 6px; position: relative; }
#papa h2 { margin: 6px 0; color: snow; font: bold 1.6em sans-serif; text-align: center; text-shadow: 2px 2px 2px #000; }
#papa p { margin: 0; padding: 6px 0; }
#papa input { border: 2px solid #ccc; border-radius: 6px; outline: none; background: none; color: snow; cursor: pointer; }
#papa input:hover { background: linear-gradient(tan,darkred); }
#papa input { display: none; }
#papa label { color: snow; }
#papa select { width: 40px; border-radius: 6px; border: 2px solid #ccc; outline: none; }
#mplayer { margin: auto; position: relative; width: 100%; height: 160px; bottom: 0; display: flex; justify-content: center; align-items: flex-end; }
#rec { margin: auto; width: 95%; height: 265px; display: block; padding: 6px; background: #efefef; color: #000; font-size: 14px; resize: none; outline: none; cursor: default; position: relative;}
#rec::-webkit-scrollbar { width: 8px; height: 4px; }
#rec::-webkit-scrollbar-thumb { border-radius: 6px; box-shadow: inset 0 0 5px rgba(0,0,0,.45); background: #fff; }
#rec::-webkit-scrollbar-track { border-radius: 6px; background: #959577; }
#selectSong { margin: 0 0 0 20px; cursor: pointer; }
#copytip { width: 550px; border: none; outline: none; background: none; color: tan; cursor: default; }
.mLine { position: relative; margin: 0 2px 0 0; width: 4px; height: 10px; background: gray linear-gradient(to top,lightgreen,green,lightgreen); }
.mLine::before, .mLine::after { position: absolute; content: ''; width: 100%; height: 3px; background: snow; top: 0; }
.mLine::after { top: 100%; }
</style>

<div id="papa">
        <h2>获取音频波形数据</h2>
        <p>
                <input id="selectSong" type="button" value="选择音乐" />
                <input type="file" id="mfile" accept=".mp3, .ogg, .wav, .acc, .webm"/>
                <input id="copy" type="button" value="复制" />
                <input id="copytip" type="text" value="" readonly />
                <label for="selectVoice">频道: </label>
                <select id="selectVoice">
                        <option value="0"> 0 </option>
                        <option value="1"> 1 </option>
                        <option value="2"> 2 </option>
                        <option value="3"> 3 </option>
                        <option value="4"> 4 </option>
                        <option value="5"> 5 </option>
                        <option value="6"> 6 </option>
                        <option value="7"> 7 </option>
                        <option value="8"> 8 </option>
                        <option value="9"> 9 </option>
                </select>
        </p>
        <p><textarea id="rec" placeholder="请选择本地音频 ..."></textarea></p>
        <div id="mplayer"></div>
</div>
<audio id="aud"></audio>

<script>

let total = Math.ceil(mplayer.offsetWidth / 6), idx = 0, voice= 0;

for(j=0; j<total; j++) {
        let el = document.createElement('span');
        el.className = 'mLine';
        mplayer.appendChild(el);
}

let Ac = new AudioContext;
let source = Ac.createMediaElementSource(aud);
let analyser = Ac.createAnalyser();
source.connect(analyser);
analyser.connect(Ac.destination);
let output = new Uint8Array(total);
let ypAr = [];
let lines = document.querySelectorAll('.mLine');

(function update() {
        analyser.getByteFrequencyData(output);
        let mid = total % 2 === 0 ? total / 2 - 1 : Math.floor(total / 2);
        for(j = 0; j < total ; j++) {
                let k = j <= mid ? (mid - j) * 2 : (j - mid) * 2 - 1;
                lines.style.height = output/2 + 'px';
        }
        window.requestAnimationFrame(update);
})();

aud.addEventListener('timeupdate', () => {
        ypAr.push(output);
        rec.value = 'ypData = [' + ypAr + '];';
        rec.scrollTop = rec.scrollHeight;
        idx ++;
});

aud.addEventListener('ended',() => {
        selectSong.disabled = selectVoice.disabled = false;
        copytip.value += ' [ ypData长度 :' + ypAr.length + ' / 音乐时长 : ' + aud.duration + ' ]';
});

copy.onclick = () => {
        rec.select();
        document.execCommand('copy');
        copytip.value = '内容已复制到剪切板';
        setTimeout("copytip.value=''",3000);
}

selectSong.onclick = () => {
        mfile.click();
        selectSong.disabled = selectVoice.disabled = true;
        ypAr.length = 0;
        rec.value = '';
}

mfile.onchange = () => {
        let filelist = mfile.files;
        if(filelist.length === 0) return;
        aud.src = URL.createObjectURL(filelist);
        aud.play();
        rec.placeholder = '音频数据待处理中 ...';
        copytip.value = '音频 : ' +filelist.name;
}

selectVoice.onchange = () => voice = selectVoice.value;

</script>

马黑黑 发表于 2022-12-8 19:53

源码下载 :

小辣椒 发表于 2022-12-8 19:54

黑黑威武,测的完美{:4_178:}

马黑黑 发表于 2022-12-8 19:58

小辣椒 发表于 2022-12-8 19:54
黑黑威武,测的完美

可以用就好

红影 发表于 2022-12-8 20:17

定稿的,就置顶了,工具类的开发很伟大,黑黑威武{:4_178:}

风中飞尘 发表于 2022-12-8 20:43

厉害搞出来了 {:4_189:}

风中飞尘 发表于 2022-12-8 20:47

有个小小的建议   就是这个频谱 我们可以自定义颜色 在线选择颜色 然后自动生成

小辣椒 发表于 2022-12-8 20:54

风中飞尘 发表于 2022-12-8 20:47
有个小小的建议   就是这个频谱 我们可以自定义颜色 在线选择颜色 然后自动生成

哈哈,又想偷懒,应该可以自己改颜色啊

小辣椒 发表于 2022-12-8 20:55

风中飞尘 发表于 2022-12-8 20:47
有个小小的建议   就是这个频谱 我们可以自定义颜色 在线选择颜色 然后自动生成

你试了不能在线修改?

风中飞尘 发表于 2022-12-8 20:58

小辣椒 发表于 2022-12-8 20:54
哈哈,又想偷懒,应该可以自己改颜色啊

自己修改麻烦啊如果一键生成自己喜欢的颜色不是更好 {:4_197:}

马黑黑 发表于 2022-12-8 21:42

风中飞尘 发表于 2022-12-8 20:47
有个小小的建议   就是这个频谱 我们可以自定义颜色 在线选择颜色 然后自动生成

这个其实也不太合适,毕竟播放器样式不是单一的,不过你可以试着弄弄

醉美水芙蓉 发表于 2022-12-8 23:12

亚伦影音工作室 发表于 2022-12-9 09:15

马老师这个得到的数据和前边的不一样,而且在我用的时候都不跳动,且用以前的数据还可以,太郁闷了。

樵歌 发表于 2022-12-9 10:09

又是一项强大有马术,可惜俺啥也不明白{:4_203:}

马黑黑 发表于 2022-12-9 11:28

亚伦影音工作室 发表于 2022-12-9 09:15
马老师这个得到的数据和前边的不一样,而且在我用的时候都不跳动,且用以前的数据还可以,太郁闷了。

道理上不应该这样。估计与帖子模板有关。

马黑黑 发表于 2022-12-9 11:28

樵歌 发表于 2022-12-9 10:09
又是一项强大有马术,可惜俺啥也不明白

吃瓜就好{:4_173:}

马黑黑 发表于 2022-12-9 13:55

今日更新:

从随机抓取的20个声音数组元素中取平均值,以解决单一音轨信息可能产生的“惰性”。
页: [1]
查看完整版本: 获取本地音频波形数据(定稿)