# 將影片之語音轉文字並結合GUI操作
## 目標
將影片內的語音轉換成文字檔儲存,並使此過程能透過圖形化介面進行操作。
## 語音轉文字
https://github.com/openai/whisper
直接利用上面現成的工具達成此目標。
```pip install -U openai-whisper```後
即可使用
### 程式碼
```python=
import whisper
file_path = "D:\starburst\stream\kirito.mp4"
model = whisper.load_model("base")
result = model.transcribe(file_path)
print(result)
```
檔案類型mp4, mp3試過可以,wav沒試過。
### 結果

這是result的內容,可以發現顯示了一堆不知道在幹嘛的東西,但那些我們暫時不需要,若只想顯示文字可以改為
```python
print(result["text"])
```

接著根據後續的需求可能還需要每段文字的開始時間以及結束時間,回去觀察前面第一張的result,發現segments似乎代表每一段文字,裡面的start和end屬性看起來又很像我們要的東西,所以試著再...再...再改一下
```python
for seg in result["segments"]:
print(seg["text"], round(seg["start"], 1), round(seg["end"], 1))
```
round(num, n)用來將num取小數點後第n位

舒服多了
## 儲存文字檔
單純只在螢幕上印出來顯然對後續操作沒有幫助,因此我們要將前面語音轉文字的結果儲存。
### 程式碼
```python=
import whisper
file_path = "D:\starburst\stream\kirito.mp4"
model = whisper.load_model("base")
result = model.transcribe(file_path)
for seg in result["segments"]:
buffer = seg["text"] + " " + (str)(round(seg["start"], 1)) + " " + (str)(round(seg["end"], 1))
with open("textAndTime.txt", "a", encoding="UTF-8") as output_file:
output_file.write(buffer)
output_file.write('\n')
with open("textOnly.txt", "a", encoding="UTF-8") as output_file:
output_file.write(result["text"])
output_file.write('\n')
```
這邊我分成兩個檔案儲存,textAndTime有紀錄每一句的開始和結束時間,textOnly則是只有純文字。
### 結果

## 圖形化介面
每次要換個檔案測試還要手動改file_path好麻煩,於是就找到了名為tkinter的模組,可以用來設計出一個具有圖形使用者介面(Graphical User Interface, GUI)的程式,而且還是Python內建的,不需要用pip安裝,直接import即可。
### 視窗
以Tk()方法建立一根視窗以放置其他元件
```python
import tkinter as tk
root = tk.Tk()
root.title("轉換的時刻到了") #視窗標題
root.geometry('700x500') #視窗尺寸
```

### 元件
目前只有使用按鈕(Button)與標籤(Label)
```python
file_path = ""
selectBtn = tk.Button(root,
text='選擇檔案',
font=('Arial',10,'bold'),
# command=selectFile
)
confirmBtn = tk.Button(root,
text='啟動',
font=('Arial',10,'bold'),
# command=start
)
pathLabel = tk.Label(root, text=file_path, font=('Arial', 10)) #字體與大小
# 位置
selectBtn.pack(anchor=tk.NW)
pathLabel.place(x=100, y=0)
confirmBtn.pack(anchor=tk.NE)
root.mainloop()
```
pack()和place()是用來調整元件在視窗中的位置,不過他有些走位很詭異,看得很矇...
下面連結有詳細說明
http://yhhuang1966.blogspot.com/2018/10/python-gui-tkinter_12.html

pathLabel這個標籤是用來顯示file_path的,但現在file_path="",所以看不到東西。
### 按鈕事件
```python
from tkinter import filedialog
file_path = ""
def update():
pathLabel.configure(text=file_path)
print("Update path success...")
def selectFile():
global file_path
file_path = filedialog.askopenfilename() # 選擇檔案後回傳檔案路徑與名稱
print(file_path) # 印出路徑
update()
selectBtn = tk.Button(root,
text='選擇檔案',
font=('Arial',10,'bold'),
command=selectFile
)
```
按鈕被點擊後會呼叫command的函數。
以上面程式碼來說,當selectBtn被點擊後,會呼叫selectFile()來選擇檔案並將路徑紀錄下來,然後進入update()裡利用configure()方法更新pathLabel的內容

可以看到成功在視窗上顯示剛選取的檔案路徑,雖然這不是重點,重點是file_path會更新成選取的路徑,切換檔案測試時就不用手動改程式碼了。
## 合體
最後將兩個合併一下就結束這一回合ㄌ
### 程式碼
```python
import tkinter as tk
from tkinter import filedialog
import whisper
root = tk.Tk()
root.title("轉換的時刻到了") #視窗標題
root.geometry('700x500') #視窗尺寸
file_path = ""
def update():
pathLabel.configure(text=file_path)
print("Update path success...")
def selectFile():
global file_path
file_path = filedialog.askopenfilename() # 選擇檔案後回傳檔案路徑與名稱
print(file_path) # 印出路徑
update()
def start():
voiceToText()
finish()
def voiceToText():
print("Converting...")
with open("textAndTime.txt", "w", encoding="UTF-8") as file:
file.write("文字+開始時間+結束時間。\n\n")
with open("textOnly.txt", "w", encoding="UTF-8") as file:
file.write("純文字。\n\n")
model = whisper.load_model("base")
result = model.transcribe(file_path)
# print(result["text"])
for seg in result["segments"]:
# print(seg["text"], round(seg["start"], 1), round(seg["end"], 1))
buffer = seg["text"] + " " + (str)(round(seg["start"], 1)) + " " + (str)(round(seg["end"], 1))
with open("textAndTime.txt", "a", encoding="UTF-8") as output_file:
output_file.write(buffer)
output_file.write('\n')
with open("textOnly.txt", "a", encoding="UTF-8") as output_file:
output_file.write(result["text"])
output_file.write('\n')
print("Text writing completed...")
def finish():
finishLabel = tk.Label(root, text="轉換完畢!!", font=('Arial',30)) # 放入標籤,使用 textvariable=text
finishLabel.place(x=200, y=200)
# Button 設定 command 參數,點擊按鈕時執行函式
selectBtn = tk.Button(root,
text='選擇檔案',
font=('Arial',10,'bold'),
command=selectFile
)
confirmBtn = tk.Button(root,
text='啟動',
font=('Arial',10,'bold'),
command=start
)
pathLabel = tk.Label(root, text=file_path, font=('Arial', 10)) #字體與大小
# 位置
selectBtn.pack(anchor=tk.NW)
pathLabel.place(x=100, y=0)
confirmBtn.pack(anchor=tk.NE)
root.mainloop()
```
### 結果
