无需跨域获取音频波形数据(初稿)
本帖最后由 马黑黑 于 2022-12-8 22:10 编辑 <br /><br /><style>#papa { margin: auto; padding: 10px; width: 740px; background: #fff; border: 1px solid #ccc; box-shadow: 2px 4px 6px #000; position: relative; }
#papa h2 { margin: 8px 0; font: bold 2em sans-serif; text-align: center; text-shadow: 2px 2px 2px #000; color: lightgreen; }
#papa input { display: 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: 260px; display: block; padding: 4px; outline: none; position: relative;}
#select { margin: 0 0 0 20px; cursor: pointer; }
#copytip { border: none; outline: none; user-select: none; cursor: default; }
.mLine { position: relative; margin: 0 2px 0 0; width: 4px; height: 10px; background: gray linear-gradient(to top,darkgreen,green,lightgreen); }
.mLine::after { position: absolute; content: ''; width: 100%; height: 3px; background: pink; top: -4px; }
</style>
<div id="papa">
<h2>获取音频波形数据</h2>
<p>
<input id="select" 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="" /><br><br>
</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);
let aa = 0;
for(j=0; j<total; j++) {
let el = document.createElement('span');
el.className = 'mLine';
mplayer.appendChild(el);
}
let lines = document.querySelectorAll('.mLine');
let context = new AudioContext;
let source = context.createMediaElementSource(aud);
let analyser = context.createAnalyser();
source.connect(analyser);
analyser.connect(context.destination);
let output = new Uint8Array(total);
let ybAr = [];
(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', () => {
ybAr.push(output);
rec.value = 'ypData = [' + ybAr + '];';
rec.scrollTop = rec.scrollHeight;
aa ++;
});
aud.addEventListener('ended',() => {
select.disabled = false;
});
copy.onclick = () => {
rec.select();
document.execCommand('copy');
copytip.value = '内容已复制到剪切板';
setTimeout("copytip.value=''",3000);
}
select.onclick = () => {
mfile.click();
select.disabled = true;
}
mfile.onchange = () => {
let filelist = mfile.files;
if(filelist.length === 0) return;
aud.src = URL.createObjectURL(filelist);
aud.play();
rec.placeholder = '音频数据处理中 ...';
}
</script> 本帖最后由 马黑黑 于 2022-12-8 11:06 编辑
文档下载:
这是初稿,应该存在诸多问题,但经测试,实现功能的核心代码是正常的
还可以这样啊{:4_178:} 黑黑太强悍了{:4_178:} 可惜现在手机{:4_198:}不能马上试 通过 input 提交的本地音频文件,解码后所得到的URL与web页运行同域,因此不再存在跨域问题!
下载二楼提供的源码,任何能运行现代浏览器的客户端都可以正常运行,当然,嫌麻烦的话也可以在线制作波形数据。
源码中的 audio 控件的 timeupdate 监听事件选取 第二个声音数组元素:
aud.addEventListener('timeupdate', () => {
ybAr.push(output);
rec.value = 'ypData = [' + ybAr + '];';
rec.scrollTop = rec.scrollHeight;
aa ++;
});
如果需要第一个元素的数据,ybAr.push(output); 中的 1 改为 0,要第二个,改为 2,其他依此类推。 小辣椒 发表于 2022-12-8 10:59
可惜现在手机不能马上试
{:4_173:} 小辣椒 发表于 2022-12-8 10:57
黑黑太强悍了
这是初稿,还有一些细节问题尚未处理,应该也存在诸多臭虫 小辣椒 发表于 2022-12-8 10:57
还可以这样啊
昨天拖地板的时候思考了一阵子,觉得可以:不就是跨域吗?我不跨还不行吗?
不跨就需要同域。别的招数木有,但可以在线解码呀,这不就解决了?
在线解码,意味着播放客户端的音频,早前在这里发过这方面的帖子,解码没问题。
解码的方式至少有两种处理思路,我用了最简单的:用 input file ,省事。 小辣椒 发表于 2022-12-8 10:59
可惜现在手机不能马上试
手机也可以操作的。不过手机下,频谱是倒过来的{:4_170:} 感谢老师的无私分享,问好! 黑黑又制作了工具书一样的帖子,真好。{:4_187:} 一边听着音乐,一边看着波形数据被一个个加载,真神奇{:4_199:} 选了个乐曲,刚开始出来的单音的时候,很多频谱还没升起来,看着很多空挡的地方。哇,一首曲子听完了,竟有这么多波形数据,太智能了{:4_173:} 呀,我接着又听一个曲子,没把原来的清除掉,那些波形数据就接着延伸下去了{:4_172:} 这倒也好,要是多曲播放的帖子,不用另外做波形数据了{:4_173:} 本帖最后由 亚伦影音工作室 于 2022-12-8 17:33 编辑
黑黑老师不抓去频谱数字用你转过来的任意数组,放上去,然后MP3任意使用,这样频谱不标准,但可解燃眉之急。我转了一个MP3数组但放上去不动!
亚伦影音工作室 发表于 2022-12-8 17:31
黑黑老师不抓去频谱数字用你转过来的任意数组,放上去,然后MP3任意使用,这样频谱不标准,但可解燃眉之急 ...
可能是数组名称的问题,我有一个示范名称误写成了 ybData,现在这个生成的波形数据是 ypData,检查一下名称前后是否一致。
也可能是其他问题所导致,需要核查代码。 红影 发表于 2022-12-8 15:41
呀,我接着又听一个曲子,没把原来的清除掉,那些波形数据就接着延伸下去了
初稿,发完后我也发现这个问题了,但作为预览,先这样,定稿版正在核验中,估计我喝完酒后就可以发出来了 红影 发表于 2022-12-8 15:42
这倒也好,要是多曲播放的帖子,不用另外做波形数据了
估计不行,衔接会有问题