懷舊風語音識別之 Speech API 聲控貪吃蛇
| | 0 | |
講到電腦語音技術,現在大家對語音識別及語音合成的想像應該都是 精準到嚇人的 OpenAI Whisper以及逼近真人的神經網路語音吧?
不過今天這個主題比較有趣,讓我們來懷舊溯往,發思古之幽情。我打算回頭玩玩已有 30 年歷史,從 Windows 95 開始內建在各版本 Windows 卻少被提起的 Microsoft Speech API。
Windows 一直有提供語音控制功能功能,但用的人不多,很少聽到相關討論。
而這套語音識別及語音合成功能,不僅供作業系統自用,開發者可透過 Microsoft Speech API 呼叫整合到程式裡,玩出有趣的應用。
以下是個超簡單的例子,在 .NET Console Application 專案參照 System.Speech,用 20 行程式就能寫出識別開放式語音內容並複誦的小程式。
using System.Speech.Recognition;
using System.Speech.Synthesis;
using (var synthesizer = new SpeechSynthesizer())
{
synthesizer.SetOutputToDefaultAudioDevice();
Action<string> speak = (text) => synthesizer.Speak(text);
using (var recognizer = new SpeechRecognitionEngine())
{
recognizer.SetInputToDefaultAudioDevice();
recognizer.LoadGrammar(new DictationGrammar());
recognizer.SpeechRecognized += (sender, e) =>
{
Console.WriteLine(e.Result.Text);
speak(e.Result.Text);
};
recognizer.RecognizeAsync(RecognizeMode.Multiple);
speak("請說指令");
Console.ReadLine();
}
}
不過只要實測一下,便會發現 SAPI 識別開放式語音內容的能力簡直廢到笑。我自信口音咬字還算標準,一句「麥克風測試」居然試了九次才成功...
颱風何時
腐壞科複合式
開始
麥克風特使
開會
率可否測試
麥克風特使
麥克風特使
麥克風測試
等等,先別急著說 SAPI 是個沒用的東西。SAPI 識別任意語音內容能力不佳,與 Whisper 的聰慧善解人意天差地遠,但如果能預先定義好幾組口語指令請它識別,則 SAPI 能用極低運算資源(與 Whisper 相比)得到十分讓人滿意的準確率。
為了證明 SAPI 還是能打的,也為了蛇年應景,各位觀眾 - 聲控貪吃蛇!!!
噗,我承認用聲控玩貪吃蛇是在搞笑,聲控的反應速度達不到遊戲所需的控制精準度,希望調到最慢還撞牆的一幕有博君一笑。不過,這個搞笑程式倒是驗證了我們能用 SAPI 精準識辨上下左右指令,意味著用它處理簡單聲控應用綽綽有餘。
SAPI 定義指令的做法透過 GrammerBuilder 定義單詞,「速度加快」、「速度減慢」則可用 GrammerBuilder("速度").Append() 串接 Choices("加快", "減慢") 組裝簡化程式,最後將所有指令組成 Choices 建立 Grammer,限縮 SAPI 語音識別範圍,效果挺讓人滿意的。
聲控指令定義程式碼如下,完整範例專案我放上 Github 了,有興趣玩玩的同學自取。
using System.Speech.Recognition;
using System.Speech.Synthesis;
using sapi_demo;
using (var synthesizer = new SpeechSynthesizer())
{
synthesizer.SetOutputToDefaultAudioDevice();
Action<string> speak = (text) => synthesizer.Speak(text);
SnakeGame snakeGame = null!;
Task task = null!;
using (var recognizer = new SpeechRecognitionEngine())
{
recognizer.SetInputToDefaultAudioDevice();
var beginCmd = new GrammarBuilder("開始");
var upCmd = new GrammarBuilder("上");
var downCmd = new GrammarBuilder("下");
var leftCmd = new GrammarBuilder("左");
var rightCmd = new GrammarBuilder("右");
var speedChg = new Choices("加快", "減慢");
var speedCmd = new GrammarBuilder("速度");
speedCmd.Append(speedChg);
var cmds = new Choices(beginCmd, upCmd, downCmd, leftCmd, rightCmd, speedCmd);
var grammar = new Grammar(cmds);
recognizer.LoadGrammar(grammar);
recognizer.SpeechRecognized += (sender, e) =>
{
switch (e.Result.Text)
{
case "開始":
if (task == null)
{
snakeGame = new SnakeGame();
task = Task.Run(() => snakeGame.Run());
}
break;
case "上":
snakeGame.SetDirection(ConsoleKey.UpArrow);
break;
case "下":
snakeGame.SetDirection(ConsoleKey.DownArrow);
break;
case "左":
snakeGame.SetDirection(ConsoleKey.LeftArrow);
break;
case "右":
snakeGame.SetDirection(ConsoleKey.RightArrow);
break;
case "速度加快":
snakeGame.SpeedUp();
break;
case "速度減慢":
snakeGame.SpeedDown();
break;
}
};
recognizer.RecognizeAsync(RecognizeMode.Multiple);
speak("請說指令");
while (task == null || !task.IsCompleted)
{
Thread.Sleep(100);
}
}
}
【結論】
即便在通用語音轉文字方面表現不佳,跟 Whisper 之類的 AI 模型非同一檔次的解決方案,但 Microsoft Speech API 具有 Windows 內建及耗用資源低兩大優勢,可輕鬆實現簡易的聲控應用。考慮 Whisper 的 CPU/GPU 高負載或語音轉文字雲端費用不低,可考慮使用 SAPI 實做喚醒詞(類似:OK Google、Hi Siri、小愛同學... ),識別到特定詞彙後再啟動高品質的語音服務,能有效節省成本,這也是 SAPI 可以發揮的經典情境。
Explored the history of Microsoft Speech API, built into Windows since 1995. Despite its poor open speech recognition, it’s effective with predefined commands. Demonstrated this with a fun voice-controlled Snake game. Full project is on GitHub.
Comments
Be the first to post a comment