使用web audio api和wavesurfer.js剪切和粘贴音频

den*_*nis 6 javascript audio html5 ruby-on-rails web-audio-api

我目前正在尝试制作一个网页编辑器,允许用户轻松调整其音频文件的基本设置,作为插件我集成了wavesurfer.js,因为它有一个非常整洁和跨浏览器的波形解决方案.

索引功能的必备列表后,我决定剪切和粘贴对于使这个产品工作至关重要,但是花了几个小时试图弄清楚如何在现有库中实现它,甚至开始重建wavesurfer.js功能从头开始理解我尚未成功的逻辑.

我的问题是,如果有人能给我一些关于如何开始构建剪切和粘贴功能的指示,或者甚至是一个非常感谢的例子.

提前致谢!

wavesurfer插件:http://wavesurfer-js.org

采摘网页编辑器 http://plucked.de

编辑解决方案(实例是waveurfer对象.):

function cut(instance){
  var selection = instance.getSelection();
  if(selection){
    var original_buffer = instance.backend.buffer;
    var new_buffer      = instance.backend.ac.createBuffer(original_buffer.numberOfChannels, original_buffer.length, original_buffer.sampleRate);

    var first_list_index        = (selection.startPosition * original_buffer.sampleRate);
    var second_list_index       = (selection.endPosition * original_buffer.sampleRate);
    var second_list_mem_alloc   = (original_buffer.length - (selection.endPosition * original_buffer.sampleRate));

    var new_list        = new Float32Array( parseInt( first_list_index ));
    var second_list     = new Float32Array( parseInt( second_list_mem_alloc ));
    var combined        = new Float32Array( original_buffer.length );

    original_buffer.copyFromChannel(new_list, 0);
    original_buffer.copyFromChannel(second_list, 0, second_list_index)

    combined.set(new_list)
    combined.set(second_list, first_list_index)

    new_buffer.copyToChannel(combined, 0);

    instance.loadDecodedBuffer(new_buffer);
  }else{
    console.log('did not find selection')
  }
}
Run Code Online (Sandbox Code Playgroud)

kat*_*ugh 8

阅读此答案建议您可以创建一个空白的AudioBuffer,其大小与要复制的音频片段大小相同(大小=以秒为单位的长度⨉采样率),然后使用片段中的数据填充其通道数据.

所以代码可能是这样的:

var originalBuffer = wavesurfer.backend.buffer;
var emptySegment = wavesurfer.backend.ac.createBuffer(
    originalBuffer.numberOfChannels,
    segmentDuration * originalBuffer.sampleRate,
    originalBuffer.sampleRate
);
for (var i = 0; i < originalBuffer.numberOfChannels; i++) {
    var chanData = originalBuffer.getChannelData(i);
    var segmentChanData = emptySegment.getChannelData(i);
    for (var j = 0, len = chanData.length; j < len; j++) {
        segmentChanData[j] = chanData[j];
    }
}

emptySegment; // Here you go!
              // Not empty anymore, contains a copy of the segment!
Run Code Online (Sandbox Code Playgroud)

  • @dennis,是的,有`wavesurfer.loadDecodedBuffer`方法,需要一个AudioBuffer.请参阅https://github.com/katspaugh/wavesurfer.js/blob/a8772b8b5148c58c231d4ad7c1d8b62f37409efb/src/wavesurfer.js#L514 (3认同)
  • 非常感谢Katspaugh!这很棒!当我将新片段粘贴到原始缓冲区时,还有一种方法可以重绘波形。 (2认同)

lll*_*lll 5

有趣的问题。我想到的第一个词是ffmpeg。我无法根据经验来谈论,但如果我试图实现这一目标,我会像这样处理它:

假设您选择音轨的一个区域,并且想要复制它并从中创建一个新轨道(稍后可能只是将其附加到现有轨道)。

  1. 使用漂亮的wavesurfer.jsgetSelection()库提供的方法。这将为您提供和[几秒钟内]。startPosition()endPosition()
  2. 鉴于这些点,您现在可以在后端使用ffmpeg选择区域并将其保存为新文件(最终将其上传到 S3 等)。请参阅此线程,了解如何从 ruby​​ 应用程序调用ffmpeg(其中显示的命令行参数也很有帮助)。

请注意,如果您计划复制并粘贴许多区域来拼凑出一条新曲目,那么始终在后端进行此操作可能没有任何意义,我想我会尝试寻找客户端 JS 方法。

我希望这至少对于一个简单的用例有帮助,并帮助您开始其余的工作;)

更新 这可能值得一读。

  • Web Audio API,教程在这里
  • HTML5 音频 - 播放状态。这里(不要错过关于 TimeRanges 的部分,看起来是一个值得尝试的合理选择)。
  • 这个(已过时,但值得一看,有趣的链接)