Ich verwende System.Speech.Synthesis.SpeechSynthesizer, um Text in Sprache zu konvertieren. Und aufgrund der anämischen Dokumentation von Microsoft (siehe meinen Link, es gibt keine Bemerkungen oder Codebeispiele) habe ich Probleme, den Unterschied zwischen zwei Methoden zu unterscheiden:TTS zum Streamen mit SpeechAudioFormatInfo mit SpeechSynthesizer
SetOutputToAudioStream und SetOutputToWaveStream.
Hier ist, was ich abgeleitet haben:
SetOutputToAudioStream einen Strom und eine SpeechAudioFormatInfo Beispiel nimmt, die das Format der Wave-Datei definiert (Samples pro Sekunde, Bits pro Sekunde, Audio-Kanäle, etc.) und schreibt den Text der Strom.
SetOutputToWaveStream nimmt nur einen Stream und schreibt eine 16 Bit, Mono, 22kHz, PCM-Wave-Datei in den Stream. Es gibt keine Möglichkeit SpeechAudioFormatInfo zu übergeben.
Mein Problem ist SetOutputToAudioStream schreibt keine gültige Wave-Datei in den Stream. Zum Beispiel bekomme ich eine InvalidOperationException ("Der Wave-Header ist beschädigt"), wenn ich den Stream an System.Media.SoundPlayer übergebe. Wenn ich den Stream auf den Datenträger schreibe und versuche, ihn mit WMP abzuspielen, erhalte ich den Fehler "Windows Media Player kann die Datei nicht abspielen ...", aber der von SetOutputToWaveStream geschriebene Stream wird in beiden korrekt wiedergegeben. Meine Theorie ist, dass SetOutputToAudioStream keinen (gültigen) Header schreibt.
Seltsamerweise sind die Namenskonventionen für SetOutputTo * Blah * inkonsistent. SetOutputToWaveFile verwendet SpeechAudioFormatInfo, SetOutputToWaveStreet dagegen nicht.
Ich muss in der Lage sein, eine 8kHz, 16-Bit, Mono-Wave-Datei in einen Stream zu schreiben, was weder SetOutputToAudioStream noch SetOutputToWaveStream mir erlaubt. Hat jemand Einblick in SpeechSynthesizer und diese beiden Methoden?
Als Referenz ist hier ein Code:
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);
}
Lösung:
Vielen Dank an @Hans Passant, hier ist der Kern dessen, was ich bin jetzt mit:
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;
Für meine grobe Tests funktioniert es gut, obwohl die Verwendung von Reflektion ein bisschen eklig ist, ist es besser, als die Datei auf die Festplatte zu schreiben und einen Stream zu öffnen.
Wenn ich darüber nachdenke, sollte das letzte Argument wahrscheinlich falsch sein, damit es den Stream nicht schließt. Wäre für einen MemoryStream nicht wichtig. –
Sie haben Recht, synth.Speak() war in der Verwendung in meinem Code. Ich habe das Code-Snippet bearbeitet. Ich gebe deinem Code eine Chance, es sieht so aus, als könnte er erreichen, was ich verlange. Ich stimme zu, dass es wie ein Versehen aussieht. Vielen Dank! – AceJordin