我有一个TTS(文本到语音)系统,它以numpy数组形式产生音频,其数据类型为np.float32
。该系统在后端运行,我想将数据从后端传输到前端,以便在发生特定事件时进行播放。
解决此问题的明显方法是将音频数据作为wav文件写入磁盘,然后将路径传递到要播放的前端。这很好,但出于管理原因,我不想这样做。我只想只将音频数据(numpy数组)传输到前端。
到目前为止,我所做的是:
text = "Hello"
wav, sr = tts_model.synthesize(text)
data = {"snd", wav.tolist()}
flask_response = app.response_class(response=flask.json.dumps(data),
status=200,
mimetype='application/json' )
# then return flask_response
// gets wav from backend
let arrayData = new Float32Array(wav);
let blob = new Blob([ arrayData ]);
let url = URL.createObjectURL(blob);
let snd = new Audio(url);
snd.play()
这是我到目前为止所做的,但是JavaScript引发以下错误:
Uncaught (in promise) DOMException: Failed to load because no supported source was found.
这是我要做的要点。很抱歉,您没有TTS系统,因此无法减少错误,因此这是它生成的audio file,可用于查看我在做什么错。
np.int8
和np.int16
在JavaScript中强制转换的Int8Array()
,int16Array()
。blob
时尝试了不同的类型,例如{"type": "application/text;charset=utf-8;"}
和{"type": "audio/ogg; codecs=opus;"}
。我已经在这个问题上苦苦挣扎了很长时间,所以请大家帮忙!!
您的样品原样无法使用。 (不播放)
但是使用:
烧瓶
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)
js
<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>
原始海报编辑
因此,在解决我的问题之前,我最终(使用此解决方案)要做的是:
np.float32
更改为np.int16
:wav = (wav * np.iinfo(np.int16).max).astype(np.int16)
scipy.io.wavfile
将numpy数组写入临时的wav文件: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")