Skip to content

Latest commit

 

History

History
226 lines (194 loc) · 8.38 KB

2023-03-01:whisper.cpp 語音轉文字教學.md

File metadata and controls

226 lines (194 loc) · 8.38 KB

2023-03-01:whisper.cpp 語音轉文字教學.md


whisper.cppOpenAI's Whisper 的 inference
支援多個語言的 speech recognition (ASR)
我玩了英文跟中文,效果很不錯


TL;TD: 直接先看結果吧

英文我用這個 talk,這是聊程式領域相關的話題

結果在這邊

選用的模型是 medium.en (下面會解釋)

中文我是用好味小姐的 podcast

結果在這邊

選用的模型是 large (下面會解釋)

下面簡單教學怎麼使用


安裝、使用

  1. clone repo https://github.com/ggerganov/whisper.cpp
  2. clone 完之後,要下載它的 model,模型有分小、中、大,跑出來的準確度也就有差
    • 中文我建議用 large (2.9 GB),英文的話,我用 medium.en (1.5 GB) 就蠻準了,英文我沒試過用 large
      • (Updated: 我後來測試 large 模型來辨識英文了,有比 medium.en 還要準,但就比較花時間)
    • 先用 cli 切到 whisper.cpp 的 folder,然後指令如下
    • medium.en 指令: bash ./models/download-ggml-model.sh medium.en
    • large 指令: bash ./models/download-ggml-model.sh large
    • 20231121 update: large 有出 v2v3 的 model 了,不過我看許多人反應 v3 的效果很差
      • large-v2 指令: bash ./models/download-ggml-model.sh large-v2
        • 如果指令認不得 large-v2 的話,你需要 git pull 更新你的 code
  3. model 下載後,cli 輸入 make 來編譯

準備檔案

  • 目前只支援 16-bit WAV 檔案,官方有提供 ffmpeg 指令來轉檔案。所以 mp4, mp3 都要先這樣轉過
  • ffmpeg -i input.mp3 -ar 16000 -ac 1 -c:a pcm_s16le output.wav

接著就可以跑了,基本的指令為

./main -m models/ggml-medium.en.bin -f samples/jfk.wav

但上面指令沒有指定出類型,結果只會 print 在 cli 上面
所以我會加上這些 flag -osrt -otxt -ovtt 來輸出 srt, vtt, txt 檔案
輸出會跟檔案同一個目錄

針對英文語音(medium.en 模型),產生 srt, vtt, txt 檔案

./main -m models/ggml-medium.en.bin -f ~/Downloads/white.wav  -osrt -otxt -ovtt

針對中文語音(large 模型),產生 srt, vtt, txt 檔案

./main -m models/ggml-large.bin -l zh -f ~/Downloads/white.wav  -osrt -otxt -ovtt

(20231121 update)
large-v2 產生 srt, vtt, txt 檔案

./main -m models/ggml-large-v2.bin -f ~/Downloads/white.wav  -osrt -otxt -ovtt
./main -m models/ggml-large-v2.bin -l zh -f ~/Downloads/white.wav  -osrt -otxt -ovtt

時間方面:

  • 1 小時的英文 talk、medium.en 模型,大概花 12 分鐘
  • 1 小時的中文 talk、medium 模型,大概花 17 分鐘
  • 1 小時的中文 talk、large 模型,大概花 30 分鐘
    • 執行的電腦是 MacBook Pro M1

有個 option 是加速 talk,但準確率會下降,我沒試過效果如何

支援的語言列表、用 -l flag 來指定

static const std::map<std::string, std::pair<int, std::string>> g_lang = {
    { "en",  { 0,  "english",         } },
    { "zh",  { 1,  "chinese",         } },
    { "de",  { 2,  "german",          } },
    { "es",  { 3,  "spanish",         } },
    { "ru",  { 4,  "russian",         } },
    { "ko",  { 5,  "korean",          } },
    { "fr",  { 6,  "french",          } },
    { "ja",  { 7,  "japanese",        } },
    { "pt",  { 8,  "portuguese",      } },
    { "tr",  { 9,  "turkish",         } },
    { "pl",  { 10, "polish",          } },
    { "ca",  { 11,  "catalan",        } },
    { "nl",  { 12,  "dutch",          } },
    { "ar",  { 13,  "arabic",         } },
    { "sv",  { 14,  "swedish",        } },
    { "it",  { 15,  "italian",        } },
    { "id",  { 16,  "indonesian",     } },
    { "hi",  { 17,  "hindi",          } },
    { "fi",  { 18,  "finnish",        } },
    { "vi",  { 19,  "vietnamese",     } },
    { "iw",  { 20,  "hebrew",         } },
    { "uk",  { 21,  "ukrainian",      } },
    { "el",  { 22,  "greek",          } },
    { "ms",  { 23,  "malay",          } },
    { "cs",  { 24,  "czech",          } },
    { "ro",  { 25,  "romanian",       } },
    { "da",  { 26,  "danish",         } },
    { "hu",  { 27,  "hungarian",      } },
    { "ta",  { 28,  "tamil",          } },
    { "no",  { 29,  "norwegian",      } },
    { "th",  { 30,  "thai",           } },
    { "ur",  { 31,  "urdu",           } },
    { "hr",  { 32,  "croatian",       } },
    { "bg",  { 33,  "bulgarian",      } },
    { "lt",  { 34,  "lithuanian",     } },
    { "la",  { 35,  "latin",          } },
    { "mi",  { 36,  "maori",          } },
    { "ml",  { 37,  "malayalam",      } },
    { "cy",  { 38,  "welsh",          } },
    { "sk",  { 39,  "slovak",         } },
    { "te",  { 40,  "telugu",         } },
    { "fa",  { 41,  "persian",        } },
    { "lv",  { 42,  "latvian",        } },
    { "bn",  { 43,  "bengali",        } },
    { "sr",  { 44,  "serbian",        } },
    { "az",  { 45,  "azerbaijani",    } },
    { "sl",  { 46,  "slovenian",      } },
    { "kn",  { 47,  "kannada",        } },
    { "et",  { 48,  "estonian",       } },
    { "mk",  { 49,  "macedonian",     } },
    { "br",  { 50,  "breton",         } },
    { "eu",  { 51,  "basque",         } },
    { "is",  { 52,  "icelandic",      } },
    { "hy",  { 53,  "armenian",       } },
    { "ne",  { 54,  "nepali",         } },
    { "mn",  { 55,  "mongolian",      } },
    { "bs",  { 56,  "bosnian",        } },
    { "kk",  { 57,  "kazakh",         } },
    { "sq",  { 58,  "albanian",       } },
    { "sw",  { 59,  "swahili",        } },
    { "gl",  { 60,  "galician",       } },
    { "mr",  { 61,  "marathi",        } },
    { "pa",  { 62,  "punjabi",        } },
    { "si",  { 63,  "sinhala",        } },
    { "km",  { 64,  "khmer",          } },
    { "sn",  { 65,  "shona",          } },
    { "yo",  { 66,  "yoruba",         } },
    { "so",  { 67,  "somali",         } },
    { "af",  { 68,  "afrikaans",      } },
    { "oc",  { 69,  "occitan",        } },
    { "ka",  { 70,  "georgian",       } },
    { "be",  { 71,  "belarusian",     } },
    { "tg",  { 72,  "tajik",          } },
    { "sd",  { 73,  "sindhi",         } },
    { "gu",  { 74,  "gujarati",       } },
    { "am",  { 75,  "amharic",        } },
    { "yi",  { 76,  "yiddish",        } },
    { "lo",  { 77,  "lao",            } },
    { "uz",  { 78,  "uzbek",          } },
    { "fo",  { 79,  "faroese",        } },
    { "ht",  { 80,  "haitian creole", } },
    { "ps",  { 81,  "pashto",         } },
    { "tk",  { 82,  "turkmen",        } },
    { "nn",  { 83,  "nynorsk",        } },
    { "mt",  { 84,  "maltese",        } },
    { "sa",  { 85,  "sanskrit",       } },
    { "lb",  { 86,  "luxembourgish",  } },
    { "my",  { 87,  "myanmar",        } },
    { "bo",  { 88,  "tibetan",        } },
    { "tl",  { 89,  "tagalog",        } },
    { "mg",  { 90,  "malagasy",       } },
    { "as",  { 91,  "assamese",       } },
    { "tt",  { 92,  "tatar",          } },
    { "haw", { 93,  "hawaiian",       } },
    { "ln",  { 94,  "lingala",        } },
    { "ha",  { 95,  "hausa",          } },
    { "ba",  { 96,  "bashkir",        } },
    { "jw",  { 97,  "javanese",       } },
    { "su",  { 98,  "sundanese",      } },
};

辨識失敗?重複辨識同樣的文字

有時候一些比較長 (> 20 mins) 的聲音使用時,會發生辨識失敗,然後一直輸出同樣的句子
像這樣

謝謝你打電話來
謝謝
謝謝
謝謝
akaaka
edt
edt
edt
edt
edt
k
edt
edt
edt
edt
...

github 上有蠻多討論的,看來還沒有完美解答

目前看到有兩個建議方案

  1. --condition_on_previous_text False,但它也可能導致輸出品質比較差
  2. 有人說用 --temperature_increment_on_fallback 比 1 好

我嘗試給這些 flag,但 whisper.cpp 不認識,我還沒找出問題
下次再研究看看