将表示为numpy数组的音频数据从python发送到Javascript
我有一个TTS(文本到语音)系统,它以numpy数组形式生成音频,其数据类型为将表示为numpy数组的音频数据从python发送到Javascript,javascript,python-3.x,numpy,flask,html5-audio,Javascript,Python 3.x,Numpy,Flask,Html5 Audio,我有一个TTS(文本到语音)系统,它以numpy数组形式生成音频,其数据类型为np.float32。这个系统在后端运行,我想将数据从后端传输到前端,以便在某个事件发生时播放 这个问题的明显解决方案是将音频数据作为wav文件写入磁盘,然后将路径传递到要播放的前端。这很好,但出于行政原因,我不想这样做。我只想将音频数据(numpy阵列)传输到前端 到目前为止,我所做的工作如下: 后端 text=“你好” wav,sr=tts_模型合成(文本) 数据={“snd”,wav.tolist()} flas
np.float32
。这个系统在后端运行,我想将数据从后端传输到前端,以便在某个事件发生时播放
这个问题的明显解决方案是将音频数据作为wav文件写入磁盘,然后将路径传递到要播放的前端。这很好,但出于行政原因,我不想这样做。我只想将音频数据(numpy阵列)传输到前端
到目前为止,我所做的工作如下:
后端
text=“你好”
wav,sr=tts_模型合成(文本)
数据={“snd”,wav.tolist()}
flask\u response=app.response\u类(response=flask.json.dumps(数据),
状态=200,
mimetype='application/json')
#然后返回您的响应
前端
//从后端获取wav
设arrayData=new Float32Array(wav);
设blob=newblob([arrayData]);
让url=url.createObjectURL(blob);
让snd=新音频(url);
snd.play()
这就是我到目前为止所做的,但是JavaScript抛出以下错误:
Uncaught (in promise) DOMException: Failed to load because no supported source was found.
这就是我想做的要点。很抱歉,您不能减少错误,因为您没有TTS系统,因此这是由它生成的,您可以使用它来查看我做错了什么
我尝试过的其他事情:
- 将音频数据类型更改为
,np.int8
,分别通过np.int16
和Int8Array()
在JavaScript中强制转换int16Array()
- 在创建
时尝试了不同的类型,例如blob
和{“type”:“application/text;charset=utf-8;”}
{“type”:“audio/ogg;codecs=opus;”}
我已经在这个问题上挣扎了这么久,所以任何帮助都是值得的 您的原样无法开箱即用。(不玩) 但是:
- 好的。从
- 您的样本编码为PCM16而不是PCM32:OK(检查wav元数据)
- 使用
将numpy数组写入临时wav文件:scipy.io.wavfile
- 从tmp文件中读取字节:
- 删除临时文件
导入io
从scipy.io.wavfile导入写入
字节\u wav=字节()
字节io=io.BytesIO(字节波形)
写入(字节io、sr、wav)
wav_bytes=byte_io.read()
音频数据=base64.b64编码(wav字节)。解码('UTF-8')
这可以直接用于创建html音频标记作为源(使用flask):
因此,您只需将wav
,sr
转换为表示原始.wav
文件的音频数据。并将其用作flask应用程序的render_模板的参数。(解决方案不发送)
或者,如果您发送音频数据
,在接受响应的.js
文件中,使用音频数据
构建url(将作为src
属性放置在html中):
//从响应中获取音频数据
设snd=新音频(“数据:音频/wav;base64,”+音频数据);
snd.play()
因为:
音频(url)
返回值:
新的HtmlLaudioElement对象,配置为用于播放url指定的文件中的音频。新对象的预加载属性设置为自动,并且其src属性设置为指定的url,如果未提供url,则设置为null。如果指定了URL,浏览器将在返回新对象之前开始异步加载媒体资源
从tts中我记得,他们发送了一个base64 buf,你试过了吗?没有,数据是在numpy
中返回的,所以你知道如何将numpy转换为base64缓冲区。。。我会用谷歌搜索一下,但也许你有一个更快的答案。我用base64.b64encode(wav)
试过了。在前端,我使用了让snd=newaudio(“data:base64,+path;)代码>但它不起作用。我尝试了数据:音频/ogg;base64,“+path;
和数据:音频/wav;base64,”+path代码>并且它们也不起作用。
from flask import Flask, render_template, json
import base64
app = Flask(__name__)
with open("sample_16.wav", "rb") as binary_file:
# Read the whole file at once
data = binary_file.read()
wav_file = base64.b64encode(data).decode('UTF-8')
@app.route('/wav')
def hello_world():
data = {"snd": wav_file}
res = app.response_class(response=json.dumps(data),
status=200,
mimetype='application/json')
return res
@app.route('/')
def stat():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug = True)
<audio controls></audio>
<script>
;(async _ => {
const res = await fetch('/wav')
let {snd: b64buf} = await res.json()
document.querySelector('audio').src="data:audio/wav;base64, "+b64buf;
})()
</script>
wav = (wav * np.iinfo(np.int16).max).astype(np.int16)
from scipy.io import wavfile
wavfile.write(".tmp.wav", sr, wav)
# read the bytes
with open(".tmp.wav", "rb") as fin:
wav = fin.read()
import os
os.remove(".tmp.wav")