从网络下载已使用 wavesurfer.js 修改的音频

2024-04-21

我使用wavesurfer.js 创建了一个多轨网络播放器,它可以调整不同轨道的级别和平移。

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

我对此做了一些研究,很多人都指出https://github.com/mattdiamond/Recorderjs https://github.com/mattdiamond/Recorderjs但四年多前,开发就停止了,从我发现的情况来看,它似乎存在很多问题。

像这样初始化它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 https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createScriptProcessor.

虽然我有一个多轨播放器,但如果我能弄清楚如何导出带有级别和平移的单轨,我就可以从那里开始。有没有其他方法可以仅使用网络音频 API 导出网络音频,或者有人可以向我指出任何其他可能有效的 js 库吗?


假设您有 PCM 音频,您可以向其中添加 RIFF/WAV 标头,从中创建 Blob,然后将 Blob 设置为对象 URLa.href属性。 StackOverflow 会阻止此处的下载,但您可以在本地运行它进行测试。希望这可以帮助! ????????

// 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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从网络下载已使用 wavesurfer.js 修改的音频 的相关文章

随机推荐

  • 从相对路径获取图像

    在我的项目中我有 2 个包 images 包含图像和通知 包含java文件 在 notification main java 中 我使用此代码从图像中获取 Image 对象 Image image Toolkit getDefaultToo
  • WebLogic Server :: 服务器不支持 J2EE Web 模块规范 3.0 版

    当我尝试使用 WebLogic 11g 10 3 5 服务器运行应用程序时 它显示 服务器不支持 J2EE Web 模块规范 3 0 版 如何克服这个问题 Thanks 使用支持的规范版本 Servlet 2 5 开发您的应用程序 或者使用
  • 在 OSX“El Capitan”上安装 wxPython 2.8(用于骑行)

    我正在尝试安装 wxPython 2 8 unicode 版本 以便能够使用 robotsframework ride 到目前为止 从网站下载的安装程序失败 并显示错误 没有可安装的软件 并且使用Brew安装3 0版本 与ride不兼容 我
  • SagePay 表单 - 经典 ASP - 使用 rijndael.asp 时缺少货币字段

    我正在尝试在经典 ASP 中添加 Form Intergration SagePay 支付网关 我有一个来自 SO 的可用 PHP 版本 我已将其翻译成 VBSCRIPT 一切似乎都工作正常 但加密除外 我使用与 PHP 脚本相同的输入 以
  • 如何在 drupal 7 中的登录表单上设置占位符

    我需要在 Drupal 7 中为水平登录表单设置一个占位符 单击时该文本需要消失 他们只会说 用户名 和 密码 这是目前表单的代码 谢谢 function horizontal login block form form action ur
  • HTTP 状态 404 – 在 Spring boot 中未找到

    我是 Spring Boot 的初学者 我想在spring boot中编写HelloWorld编程 我在运行项目时做了一个 我得到的错误是 HTTP Status 404 Not Found 到目前为止我所尝试的内容附在下面 请帮助我写出一
  • Unix 时间戳到 FAT 时间戳

    我正在尝试将时间结构转换为 FAT 时间戳 我的代码如下所示 unsigned long Fat tm struct pTime unsigned long FatTime 0 FatTime pTime seconds 2 gt gt 1
  • Firebase/Google Cloud Function 中 HTTP 请求的多次返回

    我有一个云函数 可以对我的数据库进行一些搜索 这是一个相当昂贵的过程 涉及大量的计算 它的目标是找到最好的匹配 当找到好的匹配项时 我无法提前退出 因为可能会在迭代周期的后期找到更好的匹配项 因此 理想情况下 我想定期向客户更新迄今为止最好
  • 如何使用多个XMLHttpRequest?

    我需要从 8 个不同的 URL 获取 8 个 JSON 我将必须更改的查询字符串存储在数组中 并使用 for 循环遍历它 这是我的代码 var index ESL SC2 OgamingSC2 cretetion freecodecamp
  • 通过函数更改字符串值[重复]

    这个问题在这里已经有答案了 我注意到我的代码有很多这样的语句 var some string var some func var var another func var print var outputs modified string
  • '%(FullPath)...”' aria-label='NuGet 包失败并显示“无法找到 '@(_OutputPathItem->'%(FullPath)...”'> NuGet 包失败并显示“无法找到 '@(_OutputPathItem->'%(FullPath)...”

    我正在尝试我的第一个 NuGet 包 但遇到了一些麻烦 我有一个相当简单的项目和一个非常简单的 nuspec 文件
  • HTML 表单动作搜索,1 个文本框,2 个按钮,2 个可能的结果

    这些天我正在尝试做一个搜索表单 该表单发送到两个不同的页面 其中有两个不同的按钮和一个文本框 到目前为止我正在这样做
  • 如何在SceneKit中实现逼真的景深效果?

    我正在尝试渲染具有真实景深效果的帧 我已经尝试过景深属性camera节点 但它不会产生可用的结果 是否可以切换到景深效果的最大渲染质量 性能不是一个因素 我只需要渲染一帧 用户可以等待它 SceneKit 中逼真的景深效果 在SceneKi
  • 如何在 WordPress 短代码中使用 AJAX?

    我有一个代码来显示随机报价 有人编写了一个函数来实现这一切 但由于某种原因通过AJAX更新数据不起作用 当您按下 新报价 按钮时 什么也没有发生 也许有人知道为什么 以下代码中需要修复什么 以便当您单击 新报价 时加载新报价 The PHP
  • 如何实施IDEA?

    我必须制作一个可以使用 Java 或 C 中的 IDEA 国际数据加密算法 加密和解密文本文件的应用程序 我知道Java中有一个内置的JCE Java加密扩展 但是我该如何进一步进行 有人能给我一些建议吗 由于某种原因无法发表评论 所以我将
  • 将先前的提交分解为多个提交

    如果不创建分支并在新分支上做一堆时髦的工作 是否可以在将单个提交提交到本地存储库后将其分解为几个不同的提交 git rebase i http git scm com book en v2 Git Tools Rewriting Histo
  • 如何在 EF 4.1 RC 中的 DbContext 级别关闭更改跟踪?

    我遇到了一个似乎很常见的问题 我正在更新数据库中的值 但 EF 正在使用对象的原始内存副本 并且这些更改的值不会反映在显示的数据中 我明白这是为什么 但我无法找到解决方法 最常见的解决方案似乎是设置MergeOptions NoTracki
  • OpenCV SURF功能未实现

    当我尝试运行示例时find obj cpp或任何 OpenCV SURF 程序 在执行代码时 我在命令提示符中收到以下错误 该项目构建时没有错误和警告 我使用的是 VS2011 beta OpenCV 2 4 和 windows7 错误信息
  • 附加搜索词时如何重用 jquery-ui-autocomplete 缓存结果?

    我有以下 JS 方法将 jQuery UI 自动完成小部件绑定到搜索文本框 一切工作正常 包括缓存 但在附加搜索词时我进行了不必要的服务器调用 因为我不重用刚刚检索的结果 例如 搜索 ab 会从服务器获取一些结果 在搜索框中的 ab 后面键
  • 从网络下载已使用 wavesurfer.js 修改的音频

    我使用wavesurfer js 创建了一个多轨网络播放器 它可以调整不同轨道的级别和平移 我想要做的是将具有新级别的混合曲目导出并将平移作为单个 wav 文件 我对此做了一些研究 很多人都指出https github com mattdi