我想将异步到达的文本放入一个队列中,该队列首先使用Amazon Polly生成音频流,然后依次播放生成的音频流,但是没有阻止新文本进入队列。
为了测试这个系统,我读取了写入控制台的文本。在我目前的实现中,当音频播放时,向控制台添加新文本被阻止。理想情况下,还应该可以停止当前播放的音频,并删除任何排队的语音合成请求和音频播放。
我知道正确的实现涉及线程和任务,但我目前不知道如何正确地做到这一点,因为我对c#,线程和异步编程完全陌生。请记住,Amazon Polly语音合成(SynthesizeSpeechAsync)的唯一可用实现是异步的。最终,这段代码应该与Unity引擎一起工作,通过不同的文本到语音服务在游戏中播放文本,作为一种辅助工具,为那些难以在电脑屏幕上阅读大量文本的人提供帮助。现在,让它与控制台输入一起工作是可以的。
这是我目前得到的。第一个从文本生成音频的类:
using UnityEngine;
using Amazon.Polly;
using Amazon.Polly.Model;
using NAudio.Wave;
namespace UnityTTS;
public class PollyVoiceUnity : MonoBehaviour
{
private static string awsAccessKey = "myKey";
private static string awsAccessSecret = "mySecretKey";
private static AmazonPollyClient client;
public static void Init()
{
client = new AmazonPollyClient(awsAccessKey, awsAccessSecret, Amazon.RegionEndpoint.EUWest2);
}
private async static Task<SynthesizeSpeechResponse> GetSpeechResponse(string s)
{
SynthesizeSpeechRequest synthesizeSpeechRequest = new SynthesizeSpeechRequest()
{
OutputFormat = OutputFormat.Pcm,
VoiceId = VoiceId.Brian,
TextType = TextType.Text,
Text = s,
SampleRate = "16000"
};
SynthesizeSpeechResponse synthesizeSpeechResponse = await client.SynthesizeSpeechAsync(synthesizeSpeechRequest);
return synthesizeSpeechResponse;
}
private static void PlayAudio(SynthesizeSpeechResponse response)
{
using (var ms = new MemoryStream())
{
response.AudioStream.CopyTo(ms);
byte[] buf = ms.GetBuffer();
var source = new BufferedWaveProvider(new WaveFormat(16000, 16, 1));
source.ReadFully = false;
source.AddSamples(buf, 0, buf.Length);
using (WaveOutEvent waveOut = new WaveOutEvent())
{
waveOut.Init(source);
AutoResetEvent stopped = new AutoResetEvent(false);
waveOut.PlaybackStopped += (object sender, StoppedEventArgs e) => { stopped.Set(); };
waveOut.Play();
stopped.WaitOne();
}
}
}
public async static Task AddSpeechToQueue(string s)
{
SynthesizeSpeechResponse response = await GetSpeechResponse(s);
PlayAudio(response);
return;
}
}
,然后是用于测试的主类:
using UnityTTS
class Program
{
public async static Task Main()
{
PollyVoiceUnity.Init();
string? input = "Initialized.";
while (input != "stop")
{
input = Console.ReadLine();
if (input != "stop")
{
await PollyVoiceUnity.AddSpeechToQueue(input);
}
}
}
}
我发现了这个线程,它解释了如何使用协程将Amazon Polly集成到Unity中,这更容易。你可以试着做一个深入的研究,发现一些其他的东西:
https://www.linkedin.com/pulse/guide-integrating-amazon-polly-unity-mythili-pitchika/
你也可以看看这里:https://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.htmlhttps://answers.unity.com/questions/503932/how-to-cycle-coroutine-in-c-say-every-1-sec.html