利用OPENAI: whisper來進行語音轉文字
使用whisper來進行語音轉文字,需要安裝ffmpeg和whisper套件
我的範例因為是從youtube來下載音檔所以需要額外下載YT的套件(yt-dlp)
pip install -U yt-dlp
pip install -U openai-whisper
whisper 依賴於 ffmpeg,確保已安裝並配置在系統的 PATH 中。
- 下載 [FFmpeg](https://ffmpeg.org/download.html) 並解壓縮。
- 將解壓後的目錄添加到系統 PATH:
打開「系統環境變量」 > 「環境變量」。
找到 PATH,並添加 FFmpeg 的 bin 路徑,例如 C:\ffmpeg\bin。
- 在命令行測試是否有裝成功:
ffmpeg -version
但我不知道為什麼我路徑設定後環境一直抓不到ffmpeg, 所以我是在程式碼強迫設定路徑。
— — — — — — — -
簡易執行流程:
- 設定影片URL
- 利用
yt_dlp
套件來抓YT影片音檔(mp3) - 利用whisper語法來進行語音轉文字
- 將文字寫到txt檔案內
範例影片: (我不知道有沒有版權問題,我是直接找YT公開影片來用,讀者可以自己找其他影片來做)
1. 設定影片URL
url = "https://www.youtube.com/watch?v=_5RYk2ImyS8"
2. 利用yt_dlp
套件來抓YT影片音檔(mp3):
import os
import yt_dlp
os.environ["PATH"] += r";C:\ffmpeg\bin"
def download_audio(url, output_path, filename=None):
if filename is None:
filename = url.split("=")[-1]
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': f'{output_path}/{filename}.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'ffmpeg_location': 'C:/ffmpeg/bin', # 替換為 FFmpeg 的實際路徑
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
return filename
output_path = "./mp4/"
outputFilename = download_audio(url, output_path = output_path)
print("Download audio complete!")
os.environ[“PATH”] += r”;C:\ffmpeg\bin” 這段是強迫設定ffmpeg路徑。
output_path = “./mp4/” 這段是設定下載的音檔放在哪邊,如果mp4這個folder不存在會生成一個檔案夾。
def download_audio(url, output_path, filename=None)
這個函數filename是你想要把下載的mp3檔案儲存的名稱,如果不設定就以url的編碼進行輸出。
3. 利用whisper語法來進行語音轉文字
OPENAI提供的whisper模型有提供
tiny
base
small
medium
large
large-v2
large-v3
我自己只下載medium和large-v3,理論上是執行程式他會去自動化去讀pt檔案,如果電腦預設路徑內沒有對應的pt檔,執行whisper.load_model(whisper_model_type, device=DEVICE)這段程式會自動下載
模型權重電腦預設路徑
- Linux/MacOS:
~/.cache/whisper/
- Windows:
C:\Users\<YourUsername>\.cache\whisper\
medium: pt檔案 1.42GB → 在執行模型的時候GPU會占掉 4.6 GB (見下圖)
large-v3: pt檔案 2.87GB → 在執行模型的時候GPU會占掉 9.4 GB (見下圖)
這個我懶得去看whipser的code理論上,我看whipser的語法,他應該是整個模型讀到pytorch去,然後直接執行pytorch的inference code,所以記憶體應該沒有優化到TRT內執行(這個要根據硬體編譯)此code範例應該不合適需要進行邊緣運算優化的人。
import torch
import whisper
verbose = True #是否即時顯示語音辨識結果
whisper_model_type = 'large-v3' # tiny,base,small,medium,large,large-v2,large-v3
lang = 'Chinese' #["Chinese", "English", "Japanese", "Korean"]
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
model = whisper.load_model(whisper_model_type, device=DEVICE)
result = model.transcribe(audioFile, fp16=False, verbose=verbose, language=lang)
whisper_model_type: 可以設定選擇模型。
lang: 語言設定,如果不設定,whisper也是會自動判斷。
因為我有設定verbose = True,所以他會邊執行邊寫出文字給你看,不想看的可以關掉直接改False即可。
執行結果如下:
4. 將文字寫到txt檔案內
剛剛whipser跑出來的結果是一個dict裡面的keys,可以透過whisper內的函數來寫結果檔案,預設我寫srt,這檔案就是字幕檔。
from whisper.utils import get_writer
def saveToFile(result, output_path, filename, fileType='srt') :
file_writer = get_writer(fileType, output_path)
file_writer(result, filename)
saveToFile(result, output_path=output_path, filename=outputFilename, fileType='srt')
結果會是一個srt字幕檔案,用筆記本打開如下:
我們回頭看一下「3.利用whisper語法來進行語音轉文字」跑出來的result是什麼東西,result是一個dict,裡面的key是
dict_keys([‘text’, ‘segments’, ‘language’])
text: 全部的文字,沒有時間點
segments:還是一個字典dict,裡面的key是
基本上就是把音檔的文字拆成很多個片段,用來進行時間和文字的配對用,並且以id作為分割的順序,從0開始。
我將某一個segement(‘id’: 2)拆出來給讀者看,
{‘id’: 2, ‘seek’: 0, ‘start’: 9.0, ‘end’: 11.0, ‘text’: ‘好 剛剛那份馬屁說啦’, ‘tokens’: [50815, 2131, 220, 32795, 4184, 36266, 29098, 9636, 223, 4622, 9724, 50915], ‘temperature’: 0.0, ‘avg_logprob’: -0.6901673837141558, ‘compression_ratio’: 1.32, ‘no_speech_prob’: 0.44533011317253113},
我們只要知道
id: 2 第三段個被切出來的片段,編碼從0開始。
start: text「好 剛剛那份馬屁說啦」在語音檔案的開始時間
end: text「好 剛剛那份馬屁說啦」在語音檔案的結束時間
text: 這個segement的文字是什麼
tokens: 是文字編碼,之後有空在寫這個。
你可以自己寫文字輸出方式也可以用whisper內建的函數來輸出,我建議直接用「4. 將文字寫到txt檔案內」這段內容來輸出就好。
整段程式碼整理再一起
import torch
import whisper
from whisper.utils import get_writer
import os.path
import yt_dlp
os.environ["PATH"] += r";C:\ffmpeg\bin"
def download_audio(url, output_path, filename=None):
if filename is None:
filename = url.split("=")[-1]
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': f'{output_path}/{filename}.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'ffmpeg_location': 'C:/ffmpeg/bin', # 替換為 FFmpeg 的實際路徑
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
return filename
def saveToFile(result, output_path, filename, fileType='srt') :
file_writer = get_writer(fileType, output_path)
file_writer(result, filename)
url = "https://www.youtube.com/watch?v=_5RYk2ImyS8"
output_path = "./mp4/"
verbose = True #是否即時顯示語音辨識結果
whisper_model_type = 'medium' # tiny,base,small,medium,large,large-v2,large-v3
lang = 'Chinese' #["Chinese", "English", "Japanese", "Korean"]
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
model = whisper.load_model(whisper_model_type, device=DEVICE)
# Youtube video
outputFilename = download_audio(url, output_path = output_path)
print("Download audio complete!")
audioFile = os.path.join(output_path, outputFilename+'.mp3')
file_exist = os.path.isfile(audioFile)
if file_exist:
print('processing: {}'.format(audioFile))
result = model.transcribe(audioFile, fp16=False, verbose=verbose, language=lang)
saveToFile(result, output_path=output_path, filename=outputFilename, fileType='srt')
print('done.')
else:
print('file not found')
這個範例程式流程是要下載音檔在執行語音轉換文字
如果你是電腦內有mp3檔,就可以跳過下載音檔這個程序,直接寫讀mp3程式即可。
結論
透過whisper來轉文字算滿準確的,但建議用最大的模型,我之前的課程錄影就是透過whisper來做的,但可能我大舌頭,所以轉的沒有很好還需要一個一個檔案來人工修改,但當時我是用large的模型,現在到v3了應該會好很多。
透過串接這個功能,可以達到
- 有語音剪輯的需求需要字幕的人→YT剪輯師很適合而且又不用錢。
- 要進行RAG Vector資料庫建立,如果知識是影片檔,就可以透過語音轉文字,在進行編碼建立到Vector資料庫內。
這個應該是兩年前跟學生上課時後分享的的一個小插曲,最近將之前整理的東西寫一寫分享一下。