Tôi đang sử dụng System.Speech.Synthesis.SpeechSynthesizer để chuyển đổi văn bản sang lời nói. Và do tài liệu thiếu máu của Microsoft (xem liên kết của tôi, không có nhận xét hoặc ví dụ mã) Tôi đang gặp khó khăn khi tạo đầu hoặc đuôi của sự khác biệt giữa hai phương pháp:TTS để phát trực tuyến bằng SpeechAudioFormatInfo sử dụng SpeechSynthesizer
SetOutputToAudioStream và SetOutputToWaveStream.
Dưới đây là những gì tôi đã suy luận:
SetOutputToAudioStream mất một dòng suối và một trường hợp SpeechAudioFormatInfo định nghĩa các định dạng của tập tin sóng (mẫu mỗi giây, bit mỗi giây, kênh âm thanh, vv) và viết các văn bản để dong chảy.
SetOutputToWaveStream chỉ lấy một luồng và ghi tệp sóng 16 bit, mono, 22kHz, PCM vào luồng. Không có cách nào để vượt qua trong SpeechAudioFormatInfo.
Sự cố của tôi là SetOutputToAudioStream không ghi tệp sóng hợp lệ vào luồng. Ví dụ tôi nhận được một InvalidOperationException ("Tiêu đề sóng bị hỏng") khi truyền luồng tới System.Media.SoundPlayer. Nếu tôi ghi luồng vào đĩa và cố gắng phát nó bằng WMP, tôi nhận được lỗi "Windows Media Player không thể phát tệp ..." nhưng luồng được viết bởi SetOutputToWaveStream phát đúng cách trong cả hai. Lý thuyết của tôi là SetOutputToAudioStream không viết tiêu đề (hợp lệ).
Quy ước đặt tên kỳ lạ cho SetOutputTo * Blah * không nhất quán. SetOutputToWaveFile mất một SpeechAudioFormatInfo trong khi SetOutputToWaveStream thì không.
Tôi cần có khả năng ghi một tệp sóng 8kHz, 16 bit, đơn luồng tới luồng, thứ gì đó mà cả SetOutputToAudioStream hoặc SetOutputToWaveStream đều không cho phép tôi thực hiện. Có ai có cái nhìn sâu sắc vào SpeechSynthesizer và hai phương pháp này?
Để tham khảo, đây là một số mã:
Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
synth.SelectVoice(voiceName);
synth.SetOutputToWaveStream(ret);
//synth.SetOutputToAudioStream(ret, new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
synth.Speak(textToSpeak);
}
Giải pháp:
Nhiều nhờ @Hans passant, đây là ý chính của những gì tôi đang sử dụng hiện nay:
Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
var mi = synth.GetType().GetMethod("SetOutputStream", BindingFlags.Instance | BindingFlags.NonPublic);
var fmt = new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
mi.Invoke(synth, new object[] { ret, fmt, true, true });
synth.SelectVoice(voiceName);
synth.Speak(textToSpeak);
}
return ret;
Đối với thử nghiệm thô của tôi nó hoạt động tuyệt vời, mặc dù sử dụng phản ánh là một chút icky nó tốt hơn so với ghi các tập tin vào đĩa và mở một dòng.
Hãy suy nghĩ về điều đó, đối số cuối cùng có thể là sai để nó không đóng luồng. Sẽ không quan trọng cho một MemoryStream mặc dù. –
Bạn nói đúng, synth.Speak() đã được sử dụng trong mã của tôi. Tôi đã chỉnh sửa đoạn mã. Tôi sẽ cung cấp cho mã của bạn một shot, có vẻ như nó sẽ thực hiện những gì tôi yêu cầu. Tôi đồng ý rằng nó trông giống như một sự giám sát. Cảm ơn! – AceJordin