利用OPENAI: whisper來進行語音轉文字

Tommy Huang
12 min readJan 8, 2025

--

使用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, 所以我是在程式碼強迫設定路徑。

— — — — — — — -

簡易執行流程:

  1. 設定影片URL
  2. 利用yt_dlp 套件來抓YT影片音檔(mp3)
  3. 利用whisper語法來進行語音轉文字
  4. 將文字寫到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範例應該不合適需要進行邊緣運算優化的人。

medium的模型需要4.6G的GPU RAM
large-v3的模型需要9.4G的GPU RAM
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了應該會好很多。

透過串接這個功能,可以達到

  1. 有語音剪輯的需求需要字幕的人→YT剪輯師很適合而且又不用錢。
  2. 要進行RAG Vector資料庫建立,如果知識是影片檔,就可以透過語音轉文字,在進行編碼建立到Vector資料庫內。

這個應該是兩年前跟學生上課時後分享的的一個小插曲,最近將之前整理的東西寫一寫分享一下。

--

--

Tommy Huang
Tommy Huang

Written by Tommy Huang

怕老了忘記這些吃飯的知識,開始寫文章記錄機器/深度學習相關內容。Medium現在有打賞功能(每篇文章最後面都有連結),如果覺得寫的文章不錯,也可以Donate給個Tipping吧。黃志勝 Chih-Sheng Huang (Tommy), mail: chih.sheng.huang821@gmail.com

No responses yet