问题 是否有任何用于播放flac的crossbrowser解决方案? (或理论上可以制作一个)


对silverlight不感兴趣。 Flash / javascript / html5解决方案是可以接受的。

如果您不知道这样的解决方案,请问您是否可以这样做?


9011
2017-12-13 00:31


起源

最近支持FLAC登陆Chrome。了解其工作原理的唯一方法是手动检查。 这是一个帮助它的网站。 - 0xcaff
添加了对FLAC的本机支持 在Firefox 51.0中 - cespon


答案:


一个简单的谷歌搜索引导我到这些网站:

Aurora和FLAC.js - 使用Web Audio API的音频编解码器

介绍FLAC.js:纯JavaScript FLAC解码器

信不信由你,并不是那么难。

差点忘了:
检查 HTML5Test 比较浏览器的性能/兼容性 <audio> 标签和它的兄弟姐妹。


4
2017-12-13 00:36



哇!我以为不可能用二进制数据在js中制作音频!它不支持IE,但支持Chrome / Safari / Firefox。禁止所有IE浏览器请求的充分理由。非常感谢! - avasin
不幸的是,IE是一个非常“正统”的浏览器!人们使用它的好处不那么频繁。如果我的回答符合您的问题,请将其标记为答案;) - Tico
是的,抱歉,在极光的文档中丢失)) - avasin
玩的开心!看起来很有希望。 - Tico
@avasin您是否设法弄清楚如何使用FLAC.js?我没有在任何地方看到API规范或任何指南。 - Gendarme


当我不得不在浏览器中玩FLAC时,我的出发点也是 Aurora框架

然而,Aurora播放器正在使用 ScriptProcessorNode 在运行中解码大量的音频。由于许多原因,这并没有成功。

  1. 在奥罗拉寻找Flac从未实施过。
  2. Firefox中的口吃和不可接受的性能,即使在2014年中端桌面上也是如此。
  3. 将解码卸载到WebWorker是不可行的。
  4. 不与浏览器支持的音频格式互操作。
  5. 我不想负责重新采样Aurora必须吸收的采样率,搜索和其他低级音频任务。

离线解码:Flac to Wave

我的解决方案是使用精简的Aurora.js Assset类+依赖项将Flac解码为原始16位PCM音频。
查看源代码 Asset.get('format',回调), Asset.fromFile,和 Asset.prototype.decodeToBuffer

接下来,获取音频数据以及提取的采样率和通道数值,并构建WAVE文件。这可以使用HTML5音频元素播放,通过音频图形发送 createMediaElementSource,或者你可以用本机支持的音频格式做任何事情。

注意:替换clz函数 decoder.js 与本地人 Math.clz32 提高性能,以及旧浏览器的polyfill clz32。

坏处 

解码时间。大约5秒钟,在~100%CPU上获得“平均”4分钟的歌曲。

优点

  1. Blob(与arraybuffer相对)不受RAM限制,浏览器可以将其交换到磁盘。原始Flac数据也可能被丢弃。
  2. 你可以免费寻求。
  3. 您可以免费获得采样率重新采样。
  4. 在WebWorker中预先支付的CPU活动。
  5. 浏览器是否应该获得本机Flac支持,非常容易被淘汰。它不会对Aurora产生强烈依赖。

这是构建WAVE标头的功能,并将原始PCM数据转换为浏览器可以原生播放的内容。

function createWave( audioData, sampleRate, channelCount )
{
    const audioFormat  = 1, // 2    PCM = 1
    subChunk1Size= 16,      // 4    PCM = 16
    bitsPerSample= 16,      // 2
    blockAlign   = channelCount * (bitsPerSample >> 3), // 2
    byteRate     = blockAlign * sampleRate,             // 4
    subChunk2Size= blockAlign * audioData.size,         // 4
    chunkSize    = 36 + subChunk2Size,                  // 4
    // Total header size 44 bytes
    header = new DataView( new ArrayBuffer(44) );


    header.setUint32( 0, 0x52494646 ); // chunkId=RIFF
    header.setUint32( 4, chunkSize, true );
    header.setUint32( 8, 0x57415645 ); // format=WAVE
    header.setUint32( 12, 0x666d7420 ); // subChunk1Id=fmt
    header.setUint32( 16, subChunk1Size, true );

    header.setUint16( 20, audioFormat, true );
    header.setUint16( 22, channelCount, true );

    header.setUint32( 24, sampleRate, true );
    header.setUint32( 28, byteRate, true );

    header.setUint16( 32, blockAlign, true );
    header.setUint16( 34, bitsPerSample, true );

    header.setUint32( 36, 0x64617461 ); // subChunk2Id=data
    header.setUint32( 40, subChunk2Size, true );

    return URL.createObjectURL( new Blob( [header, audioData], {type: 'audio/wav'} ) );
}

6
2018-01-20 04:28



你有一个工作演示来展示吗? :) - Jeremy Karlsson
codepen.io/enjikaka/pen/avVKGz  - 我有很多白噪声。你知道为什么吗? - Jeremy Karlsson
对不起,我触摸过这一年已经有一年了,我不再有样品了。毋庸置疑,音频数据必须是原始的16位PCM数据,具有准确的采样率和通道数。它非常脆弱。有点错误,你会听到损坏的音频。 - Adria