正在从Web下载已使用wavelesurfer.js修改的音频 [英] Downloading audio from web that has been modified with wavesurfer.js

查看:47
本文介绍了正在从Web下载已使用wavelesurfer.js修改的音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建了一个多音轨Web播放器,它使用wavelesurfer.js可以调整不同音轨的级别和平移。

我要做的是将具有新级别和平移的混合曲目导出为单个.wav文件。

我对此做了一些研究,很多人都指向https://github.com/mattdiamond/Recorderjs,但开发在4年多前就停止了,从我发现它似乎有很多问题。

仅按如下方式进行初始化:var rec = new Recorder(spectrum);我收到错误消息Cannot read property 'createScriptProcessor' of undefined at new Recorder,快速搜索后发现已弃用,请参阅https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor

虽然我有一个多音轨播放器,但如果我能想出如何用关卡和平移来输出一个音轨,我就可以从那里开始。有没有其他方法可以只用Web音频API导出Web音频,或者有谁能给我介绍其他类似的JS库,可能会起作用?

推荐答案

假设您有PCM音频,您可以向其添加一个RIFF/wav标头,从中创建一个Blob,然后将Blob设置为a.href属性上的对象URL。StackOverflow在这里阻止下载,但您可以在本地运行它以进行测试。希望这能有所帮助!🇮🇪

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
// fetch stereo PCM Float 32 little-endian file 
const url = 'https://batman.dev/static/61881209/triangle-stereo-float.pcm'

const ctx = new AudioContext()
const elStatus = document.querySelector('#status')
const elButton = document.querySelector('#download')

init().catch(showError)

async function init() {
  // get raw/PCM buffer (you will presumably already have your own)
  const buffer = await (await fetch(url)).arrayBuffer()
  
  // get WAV file bytes and audio params of your audio source
  const wavBytes = getWavBytes(buffer, {
    isFloat: true,       // floating point or 16-bit integer (WebAudio API decodes to Float32Array)
    numChannels: 2,
    sampleRate: 44100,
  })

  // add the button
  elButton.href = URL.createObjectURL(
    new Blob([wavBytes], { type: 'audio/wav' })
  )
  elButton.setAttribute('download', 'my-audio.wav') // name file
  status('')
  elButton.hidden = false
}


function status(msg) {
  elStatus.innerText = msg
}


function showError(e) {
  console.error(e)
  status(`ERROR: ${e}`)
}


// Returns Uint8Array of WAV bytes
function getWavBytes(buffer, options) {
  const type = options.isFloat ? Float32Array : Uint16Array
  const numFrames = buffer.byteLength / type.BYTES_PER_ELEMENT

  const headerBytes = getWavHeader(Object.assign({}, options, { numFrames }))
  const wavBytes = new Uint8Array(headerBytes.length + buffer.byteLength);

  // prepend header, then add pcmBytes
  wavBytes.set(headerBytes, 0)
  wavBytes.set(new Uint8Array(buffer), headerBytes.length)

  return wavBytes
}

// adapted from https://gist.github.com/also/900023
// returns Uint8Array of WAV header bytes
function getWavHeader(options) {
  const numFrames =      options.numFrames
  const numChannels =    options.numChannels || 2
  const sampleRate =     options.sampleRate || 44100
  const bytesPerSample = options.isFloat? 4 : 2
  const format =         options.isFloat? 3 : 1

  const blockAlign = numChannels * bytesPerSample
  const byteRate = sampleRate * blockAlign
  const dataSize = numFrames * blockAlign

  const buffer = new ArrayBuffer(44)
  const dv = new DataView(buffer)

  let p = 0

  function writeString(s) {
    for (let i = 0; i < s.length; i++) {
      dv.setUint8(p + i, s.charCodeAt(i))
    }
    p += s.length
  }

  function writeUint32(d) {
    dv.setUint32(p, d, true)
    p += 4
  }

  function writeUint16(d) {
    dv.setUint16(p, d, true)
    p += 2
  }

  writeString('RIFF')              // ChunkID
  writeUint32(dataSize + 36)       // ChunkSize
  writeString('WAVE')              // Format
  writeString('fmt ')              // Subchunk1ID
  writeUint32(16)                  // Subchunk1Size
  writeUint16(format)              // AudioFormat
  writeUint16(numChannels)         // NumChannels
  writeUint32(sampleRate)          // SampleRate
  writeUint32(byteRate)            // ByteRate
  writeUint16(blockAlign)          // BlockAlign
  writeUint16(bytesPerSample * 8)  // BitsPerSample
  writeString('data')              // Subchunk2ID
  writeUint32(dataSize)            // Subchunk2Size

  return new Uint8Array(buffer)
}
body {
  padding: 2rem;
  font-family: sans-serif;
  text-align: center;
}
#download {
  padding: 1em 2em;
  color: #fff;
  background: #4c8bf5;
  text-decoration: none;
}
<div id="status">Loading...</div>
<a hidden id="download">⬇ Download</a>

这篇关于正在从Web下载已使用wavelesurfer.js修改的音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆