从视频文件中提取音频
Extracting audio from a video file
编辑: 不是我的副本。我正在尝试将音频数据提取为二进制文件,像我之前提到的那样单独播放音频文件没有问题。
我正在尝试使用 Web Audio Api 从客户端的视频文件中提取音频。
var audioContext = new(window.AudioContext || window.webkitAudioContext)();
fileData = new Blob([input.files[0]]);
var videoFileAsBuffer = new Promise(getBuffer);
videoFileAsBuffer.then(function (data) {
audioContext.decodeAudioData(data).then(function (decodedAudioData) {
mySoundBuffer = decodedAudioData;
soundSource = audioContext.createBufferSource();
soundSource.buffer = mySoundBuffer;
// soundSource.connect(audioContext.destination);
// soundSource.start();
});
当我取消注释最后两行时,我听到上传的视频文件的声音。虽然,当我创建一个 link 以借助 getChannelData
方法下载文件时,它的大小几乎与视频文件相同。
我原以为 decodedAudioData
只有音频二进制数据,并将其发送到我的网络服务,这是我唯一需要的。然而,这并没有像我预期的那样成功。有人知道在客户端提取视频文件音频的方法吗?提前致谢。
这里是getBuffer
方法,以防有人想知道:
function getBuffer(resolve) {
var reader = new FileReader();
reader.onload = function () {
var arrayBuffer = reader.result;
resolve(arrayBuffer);
}
reader.readAsArrayBuffer(fileData);
}
编辑:我能够通过在 decodeAudioData 函数中使用 OfflineAudioContext 来解码视频文件并获取音频缓冲区。
var offlineAudioContext = new OfflineAudioContext(2, 44100 * 100, 44100);
var soundSource = offlineAudioContext.createBufferSource();
...
soundSource.connect(offlineAudioContext.destination);
soundSource.start();
offlineAudioContext.startRendering().then(function (renderedBuffer) {
console.log(renderedBuffer); // outputs audiobuffer
var song = audioContext.createBufferSource();
song.buffer = renderedBuffer;
song.connect(audioContext.destination);
song.start();
}).catch(function (err) {
console.log('Rendering failed: ' + err);
});
renderedBuffer
是一个音频缓冲区,输出数据没有问题,使用 Audacity 的导入原始数据选项进行了测试。但问题是,新文件(填充 renderedBuffer.getChannelData(0)
)比原始视频大。因为它只包含视频文件的音频,所以它不应该有更小的尺寸吗?
我正在使用此代码提取音频:
// initialize the audioContext
var audioContext = new webkitAudioContext();
var video = document.getElementById("myVideo");
var mediaSource = audioContext.createMediaElementSource(video);
var analyser = audioContext.createAnalyser();
mediaSource.connect(analyser);
analyser.connect(audioContext.destination);
// this will give you the sound data
video.play();
function getSoundData() {
var sample = new Float32Array(analyser.frequencyBinCount);
return analyser.getFloatFrequencyData(sample);
}
编辑:
到目前为止我还没有运行这段代码,但我认为这也应该有效:
正在将 XMLHttpRequest
提取到您的 videourl(也使用本地文件)而不是使用 WebAudio API。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://test.com/myvideo.mp4', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
var binaryData = this.response;
console.log(binaryData)
};
xhr.send();
编辑 2:
var audioFileUrl = 'video.mp3';
fetch(audioFileUrl)
.then(function(res) {
res.blob().then(function(blob) {
var size = blob.size;
var type = blob.type;
var reader = new FileReader();
reader.addEventListener("loadend", function() {
var base64FileData = reader.result.toString();
var mediaFile = {
fileUrl: audioFileUrl,
size: blob.size,
type: blob.type,
src: base64FileData
};
});
reader.readAsDataURL(blob);
});
});
或尝试使用类似这样的代码:
<audio id="audio" src="http://yourvideo.com/video.mp4" controls autoplay></audio>
function getAudio() {
var elem = document.getElementById("audio")
// get Base 64 string from elem.src
}
我希望这对我有帮助,因为到目前为止,这几行对我来说工作得很好:)
好的,其实我已经有了答案。原始音频数据非常庞大,这就是为什么它的大小甚至比视频本身还要大的原因。
var offlineAudioContext = new OfflineAudioContext(numberOfChannels, sampleRate * duration, sampleRate);
var soundSource = offlineAudioContext.createBufferSource();
...
reader.readAsArrayBuffer(blob); // video file
reader.onload = function () {
var videoFileAsBuffer = reader.result; // arraybuffer
audioContext.decodeAudioData(videoFileAsBuffer).then(function (decodedAudioData) {
myBuffer = decodedAudioData;
soundSource.buffer = myBuffer;
soundSource.connect(offlineAudioContext.destination);
soundSource.start();
offlineAudioContext.startRendering().then(function (renderedBuffer) {
console.log(renderedBuffer); // outputs audiobuffer
}).catch(function (err) {
console.log('Rendering failed: ' + err);
});
});
};
之后,我能够使用 audiobuffer-to-wav 库将音频缓冲区 (renderedbuffer) 转换为 wav 文件。 OfflineAudioContext 只需要修改裁剪后的音频。
编辑:
如果您不想覆盖音频数据,这里是 js fiddle example. decodedAudioData 方法就足够了。
编辑:
我正在尝试使用 Web Audio Api 从客户端的视频文件中提取音频。
var audioContext = new(window.AudioContext || window.webkitAudioContext)();
fileData = new Blob([input.files[0]]);
var videoFileAsBuffer = new Promise(getBuffer);
videoFileAsBuffer.then(function (data) {
audioContext.decodeAudioData(data).then(function (decodedAudioData) {
mySoundBuffer = decodedAudioData;
soundSource = audioContext.createBufferSource();
soundSource.buffer = mySoundBuffer;
// soundSource.connect(audioContext.destination);
// soundSource.start();
});
当我取消注释最后两行时,我听到上传的视频文件的声音。虽然,当我创建一个 link 以借助 getChannelData
方法下载文件时,它的大小几乎与视频文件相同。
我原以为 decodedAudioData
只有音频二进制数据,并将其发送到我的网络服务,这是我唯一需要的。然而,这并没有像我预期的那样成功。有人知道在客户端提取视频文件音频的方法吗?提前致谢。
这里是getBuffer
方法,以防有人想知道:
function getBuffer(resolve) {
var reader = new FileReader();
reader.onload = function () {
var arrayBuffer = reader.result;
resolve(arrayBuffer);
}
reader.readAsArrayBuffer(fileData);
}
编辑:我能够通过在 decodeAudioData 函数中使用 OfflineAudioContext 来解码视频文件并获取音频缓冲区。
var offlineAudioContext = new OfflineAudioContext(2, 44100 * 100, 44100);
var soundSource = offlineAudioContext.createBufferSource();
...
soundSource.connect(offlineAudioContext.destination);
soundSource.start();
offlineAudioContext.startRendering().then(function (renderedBuffer) {
console.log(renderedBuffer); // outputs audiobuffer
var song = audioContext.createBufferSource();
song.buffer = renderedBuffer;
song.connect(audioContext.destination);
song.start();
}).catch(function (err) {
console.log('Rendering failed: ' + err);
});
renderedBuffer
是一个音频缓冲区,输出数据没有问题,使用 Audacity 的导入原始数据选项进行了测试。但问题是,新文件(填充 renderedBuffer.getChannelData(0)
)比原始视频大。因为它只包含视频文件的音频,所以它不应该有更小的尺寸吗?
我正在使用此代码提取音频:
// initialize the audioContext
var audioContext = new webkitAudioContext();
var video = document.getElementById("myVideo");
var mediaSource = audioContext.createMediaElementSource(video);
var analyser = audioContext.createAnalyser();
mediaSource.connect(analyser);
analyser.connect(audioContext.destination);
// this will give you the sound data
video.play();
function getSoundData() {
var sample = new Float32Array(analyser.frequencyBinCount);
return analyser.getFloatFrequencyData(sample);
}
编辑:
到目前为止我还没有运行这段代码,但我认为这也应该有效:
正在将 XMLHttpRequest
提取到您的 videourl(也使用本地文件)而不是使用 WebAudio API。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://test.com/myvideo.mp4', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
var binaryData = this.response;
console.log(binaryData)
};
xhr.send();
编辑 2:
var audioFileUrl = 'video.mp3';
fetch(audioFileUrl)
.then(function(res) {
res.blob().then(function(blob) {
var size = blob.size;
var type = blob.type;
var reader = new FileReader();
reader.addEventListener("loadend", function() {
var base64FileData = reader.result.toString();
var mediaFile = {
fileUrl: audioFileUrl,
size: blob.size,
type: blob.type,
src: base64FileData
};
});
reader.readAsDataURL(blob);
});
});
或尝试使用类似这样的代码:
<audio id="audio" src="http://yourvideo.com/video.mp4" controls autoplay></audio>
function getAudio() {
var elem = document.getElementById("audio")
// get Base 64 string from elem.src
}
我希望这对我有帮助,因为到目前为止,这几行对我来说工作得很好:)
好的,其实我已经有了答案。原始音频数据非常庞大,这就是为什么它的大小甚至比视频本身还要大的原因。
var offlineAudioContext = new OfflineAudioContext(numberOfChannels, sampleRate * duration, sampleRate);
var soundSource = offlineAudioContext.createBufferSource();
...
reader.readAsArrayBuffer(blob); // video file
reader.onload = function () {
var videoFileAsBuffer = reader.result; // arraybuffer
audioContext.decodeAudioData(videoFileAsBuffer).then(function (decodedAudioData) {
myBuffer = decodedAudioData;
soundSource.buffer = myBuffer;
soundSource.connect(offlineAudioContext.destination);
soundSource.start();
offlineAudioContext.startRendering().then(function (renderedBuffer) {
console.log(renderedBuffer); // outputs audiobuffer
}).catch(function (err) {
console.log('Rendering failed: ' + err);
});
});
};
之后,我能够使用 audiobuffer-to-wav 库将音频缓冲区 (renderedbuffer) 转换为 wav 文件。 OfflineAudioContext 只需要修改裁剪后的音频。
编辑: 如果您不想覆盖音频数据,这里是 js fiddle example. decodedAudioData 方法就足够了。