完善的SRT字幕編輯工具:Python與Tkinter實現
一個多語言支援的GUI應用,輕鬆管理和編輯您的字幕文件
主要亮點
- 直觀的使用者界面:利用Tkinter打造易於操作的GUI,無需命令行經驗。
- 多時段保留功能:允許用戶指定多個時間範圍,靈活管理字幕內容。
- 多語言兼容性:全面支持中文、英文及日文字幕,適用於多元化需求。
專案概述
目標與需求
在視頻製作、翻譯或個人學習中,管理字幕文件(尤其是SRT格式)是一項常見需求。傳統的方法可能涉及手動編輯或使用複雜的軟體工具。本專案旨在提供一個簡單且高效的解決方案,通過Python腳本和Tkinter圖形界面,讓用戶輕鬆選擇和保留字幕中的特定時間段,刪除不需要的部分,並重新調整剩餘字幕的時間點。
功能詳解
1. 讀取與解析SRT文件
腳本首先允許用戶通過GUI選擇一個SRT字幕文件。解析過程中,程式會讀取並解析字幕文件中的每個條目,包括字幕編號、開始與結束時間,以及對應的文本內容。這確保了後續的編輯操作能夠基於精確的時間標記進行。
2. 選擇保留的時段
用戶可以在界面中輸入一個或多個時間範圍,格式為HH:MM:SS,mmm - HH:MM:SS,mmm。這些時間範圍表示用戶希望保留的字幕部分。腳本將根據這些範圍過濾並保留相應的字幕,同時刪除所有不在這些範圍內的字幕。
3. 調整字幕時間
在保留指定時段的字幕後,腳本會重新計算這些字幕的開始與結束時間,使其相對於保留時段的基準時間重新定位。這確保了生成的新SRT文件中字幕時間連續且準確。
4. 輸出新的SRT文件
完成編輯後,用戶可以選擇保存新的SRT文件。新的字幕文件將僅包含保留的時段內的字幕,並且時間點已經根據新的基準時間重新設置。此外,腳本全面支持中文、英文及日文字幕,確保多語言環境下的正常運行。
實作詳情
Python腳本與Tkinter GUI介面
以下是完整的Python腳本,該腳本使用Tkinter建立圖形用戶界面,實現讀取、編輯和保存SRT字幕文件的功能:
完整的Python腳本
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import re
from datetime import datetime, timedelta
class SubtitleEditor:
def __init__(self):
self.root = tk.Tk()
self.root.title("字幕時段編輯器")
self.root.geometry("600x500")
# 建立主框架
self.main_frame = ttk.Frame(self.root, padding="10")
self.main_frame.pack(fill=tk.BOTH, expand=True)
# 檔案選擇按鈕
self.file_btn = ttk.Button(self.main_frame, text="選擇字幕檔", command=self.select_file)
self.file_btn.pack(pady=5)
# 顯示已選擇的檔案
self.file_label = ttk.Label(self.main_frame, text="尚未選擇檔案")
self.file_label.pack(pady=5)
# 時段輸入區域
self.time_frame = ttk.LabelFrame(self.main_frame, text="保留時段", padding="5")
self.time_frame.pack(fill=tk.X, pady=5)
self.time_ranges = []
self.add_time_range()
# 新增時段按鈕
self.add_btn = ttk.Button(self.main_frame, text="新增時段", command=self.add_time_range)
self.add_btn.pack(pady=5)
# 處理按鈕
self.process_btn = ttk.Button(self.main_frame, text="處理並儲存", command=self.process_subtitle)
self.process_btn.pack(pady=5)
def add_time_range(self):
frame = ttk.Frame(self.time_frame)
frame.pack(fill=tk.X, pady=2)
start_entry = ttk.Entry(frame, width=15)
start_entry.insert(0, "00:00:00,000")
start_entry.pack(side=tk.LEFT, padx=5)
ttk.Label(frame, text="至").pack(side=tk.LEFT, padx=5)
end_entry = ttk.Entry(frame, width=15)
end_entry.insert(0, "00:00:00,000")
end_entry.pack(side=tk.LEFT, padx=5)
del_btn = ttk.Button(frame, text="刪除", command=lambda: self.delete_time_range(frame))
del_btn.pack(side=tk.LEFT, padx=5)
self.time_ranges.append((frame, start_entry, end_entry))
def delete_time_range(self, frame):
if len(self.time_ranges) > 1:
index = next(i for i, (f, _, _) in enumerate(self.time_ranges) if f == frame)
self.time_ranges.pop(index)
frame.destroy()
def select_file(self):
file_path = filedialog.askopenfilename(filetypes=[("SRT files", "*.srt")])
if file_path:
self.file_label.config(text=file_path)
self.file_path = file_path
def time_to_ms(self, time_str):
try:
time_obj = datetime.strptime(time_str, '%H:%M:%S,%f')
return (time_obj - datetime(1900, 1, 1)).total_seconds() * 1000
except ValueError:
messagebox.showerror("錯誤", f"時間格式錯誤: {time_str}")
return None
def ms_to_time(self, ms):
seconds, milliseconds = divmod(ms, 1000)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
return f"{int(hours):02}:{int(minutes):02}:{int(seconds):02},{int(milliseconds):03}"
def process_subtitle(self):
if not hasattr(self, 'file_path'):
messagebox.showerror("錯誤", "請先選擇字幕檔案!")
return
# 讀取時間範圍
time_ranges = []
for _, start_entry, end_entry in self.time_ranges:
start_ms = self.time_to_ms(start_entry.get())
end_ms = self.time_to_ms(end_entry.get())
if start_ms is None or end_ms is None:
return
if end_ms <= start_ms:
messagebox.showerror("錯誤", f"結束時間必須大於開始時間: {start_entry.get()} - {end_entry.get()}")
return
time_ranges.append((start_ms, end_ms))
# 讀取字幕檔
try:
with open(self.file_path, 'r', encoding='utf-8') as f:
content = f.read()
except Exception as e:
messagebox.showerror("錯誤", f"無法讀取檔案: {str(e)}")
return
# 解析字幕
subtitle_pattern = re.compile(r'(\d+)\n(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})\n(.*?)\n\n', re.DOTALL)
subtitles = subtitle_pattern.findall(content)
if not subtitles:
messagebox.showerror("錯誤", "字幕檔案格式不正確或為空。")
return
# 過濾並調整字幕
new_subtitles = []
current_offset = 0
for sub in subtitles:
index, start_time, end_time, text = sub
start_ms = self.time_to_ms(start_time)
end_ms = self.time_to_ms(end_time)
if start_ms is None or end_ms is None:
return
for range_start, range_end in time_ranges:
if start_ms >= range_start and end_ms <= range_end:
adjusted_start = start_ms - range_start - current_offset
adjusted_end = end_ms - range_start - current_offset
if adjusted_start < 0:
adjusted_start = 0
if adjusted_end < 0:
adjusted_end = 0
new_subtitles.append({
'number': len(new_subtitles) + 1,
'start': self.ms_to_time(adjusted_start),
'end': self.ms_to_time(adjusted_end),
'text': text.strip()
})
current_offset += (end_ms - start_ms)
break
if not new_subtitles:
messagebox.showinfo("訊息", "沒有符合保留時段的字幕。")
return
# 儲存新檔案
save_path = filedialog.asksaveasfilename(defaultextension=".srt", filetypes=[("SRT files", "*.srt")])
if save_path:
try:
with open(save_path, 'w', encoding='utf-8') as f:
for sub in new_subtitles:
f.write(f"{sub['number']}\n")
f.write(f"{sub['start']} --> {sub['end']}\n")
f.write(f"{sub['text']}\n\n")
messagebox.showinfo("完成", f"新字幕檔已保存至: {save_path}")
except Exception as e:
messagebox.showerror("錯誤", f"無法保存檔案: {str(e)}")
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = SubtitleEditor()
app.run()
使用說明
- 啟動腳本
運行上述腳本後,將彈出一個GUI界面。
- 選擇字幕檔
點擊「選擇字幕檔」按鈕,瀏覽並選擇您需要編輯的
.srt文件。 - 輸入保留時段
在「保留時段」區域,輸入您希望保留的時間範圍。例如:「00:02:15,000 - 00:02:40,000」。
如需增加多個時段,可點擊「新增時段」按鈕,並在新增的輸入框中填寫相應的時間段。
- 處理並儲存
完成時間範圍的輸入後,點擊「處理並儲存」按鈕。選擇保存新字幕文件的位置和名稱。
腳本將根據您指定的時段篩選字幕,刪除不符合條件的內容,並重新調整保留字幕的時間點。
範例演示
假設您有一個原始字幕文件如下:
1
00:00:59,002 --> 00:01:01,202
AA
2
00:02:15,045 --> 00:02:17,045
BB
3
00:02:44,908 --> 00:02:47,744
CC
4
00:04:21,371 --> 00:04:24,671
DD
您希望保留以下兩個時段:
-
00:02:15,000 - 00:02:40,000
-
00:04:20,000 - 00:04:35,000
經過腳本處理後,生成的新字幕文件將為:
1
00:00:00,045 --> 00:00:02,045
BB
2
00:00:26,371 --> 00:00:29,671
DD
技術詳細
字幕文件解析
腳本使用正則表達式來解析SRT文件中的各個段落。每個段落包含一個編號、開始和結束時間,以及字幕文本。透過解析這些信息,腳本能夠準確地識別和處理每個字幕條目。
時間格式轉換
為了便於計算,腳本將時間字串(如「00:02:15,000」)轉換為毫秒數。這使得比較和調整時間變得更加簡單和高效。轉換後的毫秒數有助於精確地篩選和重新定位字幕時間點。
字幕篩選與調整
腳本根據用戶輸入的保留時段,篩選出符合條件的字幕。隨後,腳本會重新計算這些字幕的開始和結束時間,確保它們在新的時間基準下正確顯示。這樣,不僅保留了所需的字幕內容,還確保了字幕時間的連續性和準確性。
常見問題
1. 時間格式錯誤
確保在輸入保留時段時,時間格式嚴格遵循HH:MM:SS,mmm的格式。例如:「00:02:15,000 - 00:02:40,000」。任何格式錯誤都可能導致腳本無法正確解析時間。
2. 字幕文件無法讀取
確保選擇的字幕文件是有效的SRT格式,並且編碼為UTF-8。如果文件格式不正確或編碼有問題,腳本可能無法正確讀取文件內容。
3. 沒有保留任何字幕
如果您指定的保留時段與字幕文件中的時間範圍不匹配,則可能導致沒有任何字幕被保留。請檢查您輸入的時段是否與字幕內容重疊。
參考資源
結論
通過本Python腳本,您可以輕鬆地管理和編輯SRT字幕文件,無論是為了視頻製作、語言學習還是其他用途。腳本的多時段保留功能和多語言支持,使其成為一個靈活且強大的工具。結合Tkinter建立的直觀GUI界面,即使是技術新手也能輕鬆上手,快速達成字幕編輯的需求。
Last updated January 19, 2025