Javascript 从url提取音频片段并使用纯Web音频API播放
在以下url上: 我想在Javascript 从url提取音频片段并使用纯Web音频API播放,javascript,html,xmlhttprequest,web-audio-api,audiocontext,Javascript,Html,Xmlhttprequest,Web Audio Api,Audiocontext,在以下url上: 我想在以下范围内使用纯网络音频API播放一个音频: range from: second: 306.6 range to: second: 311.8 total: 5.2 seconds 我将该文件下载到我的桌面上(我使用的是windows10),然后用VLC打开它,得到了以下文件信息: 在这里,您可以了解有关此概念的信息: 从那里我得到了以下摘录: 我想播放上面评论的范围(也粘贴在这里): 通过从支持请求头的服务器下载该片段:Range 然后我尝试了
以下范围内使用纯网络音频API
播放一个音频:
range from: second: 306.6
range to: second: 311.8
total: 5.2 seconds
我将该文件下载到我的桌面上(我使用的是windows10
),然后用VLC
打开它,得到了以下文件信息:
在这里,您可以了解有关此概念的信息:
从那里我得到了以下摘录:
我想播放上面评论的范围
(也粘贴在这里):
通过从支持请求头的服务器下载该片段:Range
然后我尝试了以下代码:
...
let num_channels = 2;
let sample_rate = 44100;
let range_from = 0; // Goal: 306.6 seconds
let range_length = (sample_rate / num_channels) * 5.2; // Goal: 5.2 seconds
let range_to = range_from + (range_length - 1); // "range_to" is inclusive (confirmed)
request.setRequestHeader("Range", "bytes=" + range_from + "-" + range_to);
...
我的问题是:
我需要为变量找到正确的值:range\u from
,以便它从第二个开始播放:306.6
我想知道上面为:range\u length
指定的值是否正确,因为可能有字节用于标题等,我的意思是:标题
+数据
这是我到目前为止的代码:
window.AudioContext=window.AudioContext | | window.webkitadiocontext;//对于iPhone来说是必要的(可能是其他的)。可能在不久的将来改变。
常量URL=https://www.tophtml.com/snl/15.mp3';
const context=新的AudioContext();
addEventListener('load',function()){
const button_option_1=document.querySelector('.button_option_1');
const button_option_1_play=document.querySelector('.button_option_1_play');
按钮\u选项\u 1\u播放。禁用=真;
按钮选项1.addEventListener('click',异步函数(){
让时间开始,持续时间;
让缓冲;
日志(“…”,false);
按钮\u选项\u 1\u play.disabled=true;
按钮_选项_1 _play.onclick=()=>playBuffer(缓冲区);
//---
time_start=new Date().getTime();
让arrayBuffer=等待获取(URL);
//下载完整
持续时间=sprintf('%.2fs',(新日期().getTime()-time\u开始)/1000);
日志(sprintf('P2.Delay:+%s用于下载。等待…',持续时间));
//---
time_start=new Date().getTime();
let audioBuffer=等待解码音频数据(上下文,arrayBuffer);
//解码完成
持续时间=sprintf('%.2fs',(新日期().getTime()-time\u开始)/1000);
日志(sprintf('P3.延迟:+%s用于解码',持续时间));
//---
按钮\u选项\u 1\u play.disabled=false;
缓冲区=音频缓冲区;
按钮选项1播放。单击();
});
});
功能播放缓冲区(缓冲区、起始区、持续时间){
const source=context.createBufferSource();//源的类型:“AudioBufferSourceNode”
source.buffer=缓冲区;
source.connect(context.destination);
source.start(context.currentTime、from、duration);
}
函数日志(text,append=true){
让log=document.querySelector('.log');
如果(!追加)
log.innerHTML='';
让entry=document.createElement('div');
entry.innerHTML=文本;
log.appendChild(条目);
}
函数解码音频数据(上下文,arrayBuffer){
返回新承诺(异步(解析、拒绝)=>{
if(false){}
else if(context.decodeAudioData.length==1){
//console.log(“解码音频数据/方式1”);
让audioBuffer=等待上下文。解码AudioData(arrayBuffer);
解析(音频缓冲);
}
else if(context.decodeAudioData.length==2){
//iPhone(Safari,Chrome)和Mac(Safari)所必需的。可能在不久的将来改变。
//console.log(“解码音频数据/方式2”);
解码音频数据(arrayBuffer,函数onSuccess(audioBuffer){
解析(音频缓冲);
});
}
});
}
函数获取(url){
返回新承诺((解决、拒绝)=>{
var request=new XMLHttpRequest();
打开('GET',url,true);
request.responseType='arraybuffer';
设num_通道=2;
样本率=44100;
让范围_from=0;//目标:306.6秒
让范围长度=(采样率/通道数)*5.2;//目标:5.2秒
让range_to=range_from+(range_length-1);/“range_to”包含在内(已确认)
setRequestHeader(“Range”,“bytes=“+Range\u from+”-“+Range\u to”);
request.onload=函数(){
让arrayBuffer=request.response;
let byteArray=新的UINT8阵列(arrayBuffer);
//console.log(Array.from(byteArray));//只记录信息
解决(arrayBuffer);
}
request.send();
});
}
.log{
显示:内联块;
字体系列:“Courier New”,Courier,monospace;
字体大小:13px;
边缘顶部:10px;
填充:4px;
背景色:#d4e4ff;
}
.分隔器{
边框顶部:1px实心#ccc;
利润率:10px0;
}
选择1
播放
[空]
帧长度(秒)=帧采样数/采样率,即38.28帧/秒
帧长度(字节)=144*比特率/采样率
因此,fetch()现在应该可以工作了(我也更改了范围长度):
函数获取(url){
返回新承诺((解决、拒绝)=>{
var request=new XMLHttpRequest();
打开('GET',url,true);
request.responseType='arraybuffer';
设num_通道=2;
比特率=192000;
样本率=44100;
设字节/秒=144*(比特率/采样率)*38.28;
let range_from=数学地板(字节/u秒*306.6);
let range_length=数学地板(字节/秒*5.2);
让range_to=range_from+(range_length-1);
setRequestHeader(“Range”,“bytes=“+Range\u from+”-“+Range\u to”);
request.onload=函数(){
让arrayBuffer=request.response;
let byteArray=新的UINT8阵列(arrayBuffer);
//******************
for(设i=0;irange from: second: 306.6
range to: second: 311.8
total: 5.2 seconds
...
let num_channels = 2;
let sample_rate = 44100;
let range_from = 0; // Goal: 306.6 seconds
let range_length = (sample_rate / num_channels) * 5.2; // Goal: 5.2 seconds
let range_to = range_from + (range_length - 1); // "range_to" is inclusive (confirmed)
request.setRequestHeader("Range", "bytes=" + range_from + "-" + range_to);
...
function fetch(url) {
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
let num_channels = 2;
let bitrate = 192000;
let sample_rate = 44100;
let byte_per_sec = 144 * (bitrate/sample_rate) * 38.28;
let range_from = Math.floor(byte_per_sec * 306.6);
let range_length = Math.floor(byte_per_sec * 5.2);
let range_to = range_from + (range_length - 1);
request.setRequestHeader("Range", "bytes=" + range_from + "-" + range_to);
request.onload = function() {
let arrayBuffer = request.response;
let byteArray = new Uint8Array(arrayBuffer);
//******************
for ( let i = 0; i < byteArray.length; i += 1 ) {
if (( byteArray[i] === 0b11111111 ) && ( byteArray[ i + 1 ] & 0b11110000 ) === 0b11110000 ){
log('we have a winner! Frame header at:'+i, true);
console.log((parseInt(byteArray[i], 10)).toString(2)); //frame header 4 bytes
console.log((parseInt(byteArray[i+1], 10)).toString(2));
console.log((parseInt(byteArray[i+2], 10)).toString(2));
console.log((parseInt(byteArray[i+3], 10)).toString(2));
resolve(arrayBuffer.slice(i));
break;
}
}
//******************
}
request.send();
});
}