前端实现从视频中抽离出音频

首先声明:也不是原创,看同事做了这个需求,感觉很炸,就了解了下  发现csdn 并没有类似功能  所以发表一份

总共两份 一份是插件,一份是插件运用 

插件名称 audiobuffer-to-wav   

npm依赖 

 

npm install audiobuffer-to-wav --save

 

这是插件

function audioBufferToWav (buffer, opt) {
  opt = opt || {}

  var numChannels = buffer.numberOfChannels
  var sampleRate = buffer.sampleRate
  var format = opt.float32 ? 3 : 1
  var bitDepth = format === 3 ? 32 : 16

  var result
  if (numChannels === 2) {
    result = interleave(buffer.getChannelData(0), buffer.getChannelData(1))
  } else {
    result = buffer.getChannelData(0)
  }

  return encodeWAV(result, format, sampleRate, numChannels, bitDepth)
}

function encodeWAV (samples, format, sampleRate, numChannels, bitDepth) {
  var bytesPerSample = bitDepth / 8
  var blockAlign = numChannels * bytesPerSample

  var buffer = new ArrayBuffer(44 + samples.length * bytesPerSample)
  var view = new DataView(buffer)

  /* RIFF identifier */
  writeString(view, 0, 'RIFF')
  /* RIFF chunk length */
  view.setUint32(4, 36 + samples.length * bytesPerSample, true)
  /* RIFF type */
  writeString(view, 8, 'WAVE')
  /* format chunk identifier */
  writeString(view, 12, 'fmt ')
  /* format chunk length */
  view.setUint32(16, 16, true)
  /* sample format (raw) */
  view.setUint16(20, format, true)
  /* channel count */
  view.setUint16(22, numChannels, true)
  /* sample rate */
  view.setUint32(24, sampleRate, true)
  /* byte rate (sample rate * block align) */
  view.setUint32(28, sampleRate * blockAlign, true)
  /* block align (channel count * bytes per sample) */
  view.setUint16(32, blockAlign, true)
  /* bits per sample */
  view.setUint16(34, bitDepth, true)
  /* data chunk identifier */
  writeString(view, 36, 'data')
  /* data chunk length */
  view.setUint32(40, samples.length * bytesPerSample, true)
  if (format === 1) { // Raw PCM
    floatTo16BitPCM(view, 44, samples)
  } else {
    writeFloat32(view, 44, samples)
  }

  return buffer
}

function interleave (inputL, inputR) {
  var length = inputL.length + inputR.length
  var result = new Float32Array(length)

  var index = 0
  var inputIndex = 0

  while (index < length) {
    result[index++] = inputL[inputIndex]
    result[index++] = inputR[inputIndex]
    inputIndex++
  }
  return result
}

function writeFloat32 (output, offset, input) {
  for (var i = 0; i < input.length; i++, offset += 4) {
    output.setFloat32(offset, input[i], true)
  }
}

function floatTo16BitPCM (output, offset, input) {
  for (var i = 0; i < input.length; i++, offset += 2) {
    var s = Math.max(-1, Math.min(1, input[i]))
    output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true)
  }
}

function writeString (view, offset, string) {
  for (var i = 0; i < string.length; i++) {
    view.setUint8(offset + i, string.charCodeAt(i))
  }
}

 

代码运用

 

function extractAudioFromVideo (videoUrl){
    var audioContext = new (window.AudioContext || window.webkitAudioContext)();
    var reader = new FileReader();
    var myBuffer;
    const sampleRate = 16000;
    const numberOfChannels = 1;

    return new Promise((resolve, reject) => {
      fetch(videoUrl, {
        responseType: "blob",
      })
        .then((res) => res.blob())
        .then((blob) => {
          reader.readAsArrayBuffer(blob);
        });

      reader.onload = function () {
        var videoFileAsBuffer = reader.result;
        audioContext.decodeAudioData(videoFileAsBuffer).then(function (decodedAudioData) {
            var duration = decodedAudioData.duration;
            var offlineAudioContext = new OfflineAudioContext(
              numberOfChannels,
              sampleRate * duration,
              sampleRate
            );
            var soundSource = offlineAudioContext.createBufferSource();

            myBuffer = decodedAudioData;
            soundSource.buffer = myBuffer;
            soundSource.connect(offlineAudioContext.destination);
            soundSource.start();

            offlineAudioContext.startRendering().then(function (renderedBuffer) {
                var wav = audioBufferToWav(renderedBuffer);
                var blob = new window.Blob([new DataView(wav)], {
                  type: "audio/wav",
                });
                resolve(window.URL.createObjectURL(blob));
              })
              .catch(function (err) {
                reject(err);
              });
          });
      };
    });
  };
  console.log(extractAudioFromVideo('http://mgcdn.vod.migucloud.com/vi1/1088.2qpLJaD2F4R8O2Cv7t07j9.0.pSF3ZI.mp4'))

 

 

最后返回的是一个promise 

 

 最后我想说下,因为这个是异步处理,需要蛮长时间去抽离文件,所以如果没有必要  可以直接放两个video去加载。一个显示一个隐藏。加载一个视频地址,浏览器缓存一个文件 也是很快的。。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值