Ithy Logo

創建一個多語言支持的Python字幕過濾腳本

高效處理.srt檔案,保留所需時段的字幕內容

python srt subtitle processing

主要要點

  • 多語言支持:腳本支持中文、英文及日文字幕,滿足廣泛的使用需求。
  • 互動式時間範圍選擇:用戶可以靈活輸入多個想保留的時間段,簡化字幕過濾流程。
  • 高效且可靠:利用pysrt庫進行字幕處理,確保操作的準確性和穩定性。

概述

在處理視頻字幕時,經常需要根據特定需求保留或刪除某些時間段的字幕內容。本文將詳細介紹如何使用Python編寫一個腳本,實現讀取.srt字幕檔案,讓用戶選擇保留的時間段,並生成新的.srt檔案。此腳本支持中文、英文及日文字幕,適用於各種多語言環境。

環境準備

安裝必要的Python庫

在開始之前,請確保已安裝Python 3.6以上版本。接下來,安裝處理字幕的pysrt庫:


pip install pysrt
    

如需處理檔案編碼,還需要安裝Chardet庫:


pip install chardet
    

完整的Python腳本

以下是完整的Python腳本,實現讀取.srt檔案,讓用戶選擇保留的時間段,並生成新的.srt檔案:


import pysrt
from datetime import datetime, timedelta
import os
import chardet

def detect_encoding(file_path):
    """檢測檔案編碼"""
    with open(file_path, 'rb') as f:
        result = chardet.detect(f.read())
    return result['encoding']

def parse_time_input(time_str):
    """
    將用戶輸入的時間字串轉換為timedelta物件
    支持格式:HH:MM:SS,mmm 或 HH:MM:SS
    """
    try:
        if ',' in time_str:
            time_part, ms_part = time_str.split(',')
            dt = datetime.strptime(time_part, "%H:%M:%S")
            return timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second, milliseconds=int(ms_part))
        else:
            dt = datetime.strptime(time_str, "%H:%M:%S")
            return timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second)
    except ValueError:
        return None

def get_time_ranges():
    """獲取使用者想要保留的時間範圍"""
    ranges = []
    print("\n請輸入要保留的時間範圍 (格式: HH:MM:SS,mmm - HH:MM:SS,mmm)")
    print("例如:00:02:15,000 - 00:02:40,000")
    print("輸入 'done' 完成輸入\n")
    
    while True:
        time_range = input("請輸入時間範圍或 'done': ").strip()
        if time_range.lower() == 'done':
            break
        if '-' not in time_range:
            print("格式錯誤,請使用 '開始時間 - 結束時間' 格式。")
            continue
        start_str, end_str = map(str.strip, time_range.split('-', 1))
        start_td = parse_time_input(start_str)
        end_td = parse_time_input(end_str)
        if start_td is None or end_td is None:
            print("時間格式錯誤,請重新輸入。")
            continue
        if start_td >= end_td:
            print("開始時間必須早於結束時間。")
            continue
        ranges.append((start_td, end_td))
    return ranges

def is_subtitle_in_ranges(sub, ranges):
    """檢查字幕是否在保留範圍內"""
    sub_start = timedelta(hours=sub.start.hours, minutes=sub.start.minutes, seconds=sub.start.seconds, milliseconds=sub.start.milliseconds)
    sub_end = timedelta(hours=sub.end.hours, minutes=sub.end.minutes, seconds=sub.end.seconds, milliseconds=sub.end.milliseconds)
    for start, end in ranges:
        # 若字幕的任何部分在範圍內,則保留
        if sub_start < end and sub_end > start:
            return True
    return False

def process_subtitle_file():
    """主函數:處理字幕檔案"""
    input_file = input("請輸入.srt檔案路徑: ").strip()
    if not os.path.isfile(input_file):
        print("檔案不存在,請確認路徑後重試。")
        return
    
    encoding = detect_encoding(input_file)
    try:
        subs = pysrt.open(input_file, encoding=encoding)
    except Exception as e:
        print(f"無法讀取字幕檔案:{e}")
        return
    
    print("\n檔案中共包含 {0} 條字幕。".format(len(subs)))
    ranges = get_time_ranges()
    if not ranges:
        print("未輸入任何保留的時間範圍,無需處理。")
        return
    
    filtered_subs = pysrt.SubRipFile()
    for sub in subs:
        if is_subtitle_in_ranges(sub, ranges):
            filtered_subs.append(sub)
    
    if not filtered_subs:
        print("未找到符合保留範圍的字幕。")
        return
    
    # 重新編排字幕編號
    for idx, sub in enumerate(filtered_subs, start=1):
        sub.index = idx
    
    output_file = os.path.splitext(input_file)[0] + "_filtered.srt"
    try:
        filtered_subs.save(output_file, encoding='utf-8')
        print(f"成功生成新的字幕檔案:{output_file}")
    except Exception as e:
        print(f"無法保存字幕檔案:{e}")

if __name__ == "__main__":
    process_subtitle_file()
    

腳本解析

功能介紹

這個腳本的主要功能包括:

  1. 檔案編碼檢測:使用chardet庫自動檢測.srt檔案的編碼,確保正確讀取字幕內容。
  2. 時間範圍輸入:用戶可以輸入多個想要保留的時間段,格式為「開始時間 - 結束時間」,例如「00:02:15,000 - 00:02:40,000」。
  3. 字幕過濾:根據用戶輸入的時間範圍,篩選出在這些範圍內的字幕,並刪除其他字幕。
  4. 保存新檔案:將篩選後的字幕保存為新的.srt檔案,檔名以「_filtered」結尾。

詳細說明

1. 檢測檔案編碼

使用chardet庫來自動檢測輸入檔案的編碼方式,確保pysrt能夠正確讀取字幕內容。


def detect_encoding(file_path):
    """檢測檔案編碼"""
    with open(file_path, 'rb') as f:
        result = chardet.detect(f.read())
    return result['encoding']
    

2. 解析用戶輸入的時間

將用戶輸入的時間字串轉換為timedelta物件,以便後續進行時間比較。


def parse_time_input(time_str):
    """
    將用戶輸入的時間字串轉換為timedelta物件
    支持格式:HH:MM:SS,mmm 或 HH:MM:SS
    """
    try:
        if ',' in time_str:
            time_part, ms_part = time_str.split(',')
            dt = datetime.strptime(time_part, "%H:%M:%S")
            return timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second, milliseconds=int(ms_part))
        else:
            dt = datetime.strptime(time_str, "%H:%M:%S")
            return timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second)
    except ValueError:
        return None
    

3. 獲取用戶輸入的時間範圍

通過互動式輸入,讓用戶可以輸入多個想要保留的時間範圍,並存儲在列表中。


def get_time_ranges():
    """獲取使用者想要保留的時間範圍"""
    ranges = []
    print("\n請輸入要保留的時間範圍 (格式: HH:MM:SS,mmm - HH:MM:SS,mmm)")
    print("例如:00:02:15,000 - 00:02:40,000")
    print("輸入 'done' 完成輸入\n")
    
    while True:
        time_range = input("請輸入時間範圍或 'done': ").strip()
        if time_range.lower() == 'done':
            break
        if '-' not in time_range:
            print("格式錯誤,請使用 '開始時間 - 結束時間' 格式。")
            continue
        start_str, end_str = map(str.strip, time_range.split('-', 1))
        start_td = parse_time_input(start_str)
        end_td = parse_time_input(end_str)
        if start_td is None or end_td is None:
            print("時間格式錯誤,請重新輸入。")
            continue
        if start_td >= end_td:
            print("開始時間必須早於結束時間。")
            continue
        ranges.append((start_td, end_td))
    return ranges
    

4. 檢查字幕是否在保留範圍內

對於每一條字幕,檢查其開始或結束時間是否在任何一個保留的時間範圍內。


def is_subtitle_in_ranges(sub, ranges):
    """檢查字幕是否在保留範圍內"""
    sub_start = timedelta(hours=sub.start.hours, minutes=sub.start.minutes, seconds=sub.start.seconds, milliseconds=sub.start.milliseconds)
    sub_end = timedelta(hours=sub.end.hours, minutes=sub.end.minutes, seconds=sub.end.seconds, milliseconds=sub.end.milliseconds)
    for start, end in ranges:
        # 若字幕的任何部分在範圍內,則保留
        if sub_start < end and sub_end > start:
            return True
    return False
    

5. 處理字幕檔案並保存新檔案

根據用戶輸入的時間範圍,篩選出符合條件的字幕,並保存為新的.srt檔案。


def process_subtitle_file():
    """主函數:處理字幕檔案"""
    input_file = input("請輸入.srt檔案路徑: ").strip()
    if not os.path.isfile(input_file):
        print("檔案不存在,請確認路徑後重試。")
        return
    
    encoding = detect_encoding(input_file)
    try:
        subs = pysrt.open(input_file, encoding=encoding)
    except Exception as e:
        print(f"無法讀取字幕檔案:{e}")
        return
    
    print("\n檔案中共包含 {0} 條字幕。".format(len(subs)))
    ranges = get_time_ranges()
    if not ranges:
        print("未輸入任何保留的時間範圍,無需處理。")
        return
    
    filtered_subs = pysrt.SubRipFile()
    for sub in subs:
        if is_subtitle_in_ranges(sub, ranges):
            filtered_subs.append(sub)
    
    if not filtered_subs:
        print("未找到符合保留範圍的字幕。")
        return
    
    # 重新編排字幕編號
    for idx, sub in enumerate(filtered_subs, start=1):
        sub.index = idx
    
    output_file = os.path.splitext(input_file)[0] + "_filtered.srt"
    try:
        filtered_subs.save(output_file, encoding='utf-8')
        print(f"成功生成新的字幕檔案:{output_file}")
    except Exception as e:
        print(f"無法保存字幕檔案:{e}")
    

使用說明

步驟一:運行腳本

在命令行或終端中導航到腳本所在目錄,並運行:


python your_script_name.py
    

步驟二:輸入字幕檔案路徑

當提示輸入.srt檔案路徑時,輸入字幕檔案的完整路徑,例如:


請輸入.srt檔案路徑: /path/to/your/subtitle.srt
    

步驟三:輸入保留的時間範圍

根據提示,輸入要保留的時間段,可以輸入多個範圍。例如:


請輸入時間範圍或 'done': 00:02:15,000 - 00:02:40,000
請輸入時間範圍或 'done': 00:05:00,000 - 00:05:30,000
請輸入時間範圍或 'done': done
    

輸入完成後,腳本將自動過濾並保留指定時間段內的字幕。

步驟四:查看並使用新字幕檔案

腳本將生成一個新的.srt檔案,檔名為原檔名加上「_filtered」。例如:「subtitle_filtered.srt」。

測試與驗證

準備測試字幕檔

在測試腳本前,準備一個包含多條字幕的.srt檔案,並確保檔案編碼為UTF-8、CP950等以支持中文、英文或日文字幕。

範例時間範圍輸入

輸入格式需嚴格遵守,以下為範例:


開始時間:00:01:00,000
結束時間:00:02:00,000
    

這將保留從1分鐘到2分鐘之間的字幕內容。

注意事項

  • 時間範圍的格式必須正確,否則腳本將提示錯誤並要求重新輸入。
  • 確保開始時間早於結束時間。
  • 若不保留任何字幕,生成的新檔案將為空。

進階應用

自動化批量處理

若需處理多個.srt檔案,可將腳本稍作修改,批量處理指定目錄下的所有字幕檔。

示例代碼:


import glob

def batch_process(directory, ranges):
    """批量處理指定目錄下的所有.srt檔案"""
    srt_files = glob.glob(os.path.join(directory, "*.srt"))
    for file in srt_files:
        try:
            subs = pysrt.open(file, encoding=detect_encoding(file))
            filtered_subs = pysrt.SubRipFile()
            for sub in subs:
                if is_subtitle_in_ranges(sub, ranges):
                    filtered_subs.append(sub)
            if not filtered_subs:
                print(f"{file} 無符合範圍的字幕,跳過。")
                continue
            for idx, sub in enumerate(filtered_subs, start=1):
                sub.index = idx
            output_file = os.path.splitext(file)[0] + "_filtered.srt"
            filtered_subs.save(output_file, encoding='utf-8')
            print(f"已生成:{output_file}")
        except Exception as e:
            print(f"處理 {file} 時出錯:{e}")
    

整合GUI界面

為了提升用戶體驗,可以使用Tkinter等庫為腳本添加圖形用戶界面(GUI)。這樣,用戶無需在命令行中操作,只需通過點擊和輸入即可完成字幕的過濾。

簡單的Tkinter示例:


import tkinter as tk
from tkinter import filedialog, messagebox

def select_file():
    file_path = filedialog.askopenfilename(filetypes=[("SRT files", "*.srt")])
    entry_file.delete(0, tk.END)
    entry_file.insert(0, file_path)

def start_processing():
    file_path = entry_file.get()
    if not file_path:
        messagebox.showerror("錯誤", "請選擇.srt檔案。")
        return
    # 此處調用process_subtitle_file的相關函數並傳遞參數
    # 需要進一步實現GUI的時間範圍輸入
    messagebox.showinfo("完成", "字幕過濾完成。")

root = tk.Tk()
root.title("字幕過濾器")

tk.Label(root, text="選擇.srt檔案:").grid(row=0, column=0, padx=10, pady=10)
entry_file = tk.Entry(root, width=50)
entry_file.grid(row=0, column=1, padx=10, pady=10)
tk.Button(root, text="瀏覽", command=select_file).grid(row=0, column=2, padx=10, pady=10)
tk.Button(root, text="開始過濾", command=start_processing).grid(row=1, column=1, pady=20)

root.mainloop()
    

常見問題解答

Q1:為什麼腳本無法讀取我的.srt檔案?

A1:請確保.srt檔案存在且路徑正確。此外,確保檔案編碼為UTF-8或CP950,如有其他編碼,請相應調整。

Q2:我輸入的時間範圍格式錯誤,該怎麼辦?

A2:請嚴格按照「HH:MM:SS,mmm - HH:MM:SS,mmm」格式輸入。例如:「00:02:15,000 - 00:02:40,000」。確保使用逗號分隔秒和毫秒部分。

Q3:生成的新.srt檔案沒有任何內容,這正常嗎?

A3:這表示沒有任何一條字幕位於您指定的保留範圍內。請檢查您的時間範圍是否正確,並確保範圍內確實有字幕。

結論

通過本文提供的詳細Python腳本,您可以輕鬆地過濾.srt字幕檔案中的特定時間段,保留所需的字幕內容。腳本不僅支持多種語言,還具有良好的擴展性,適用於各種不同的使用場景。無論是個人視頻編輯還是專業字幕處理,此腳本都能提供極大的便利。

參考資料

常見錯誤排查

錯誤1:字幕時間格式錯誤

確保字幕的時間格式嚴格遵循.srt標準格式,即「HH:MM:SS,mmm」。任何偏離此格式的時間都可能導致解析失敗。

錯誤2:pysrt無法正確解析字幕

這可能是由於檔案編碼問題或字幕檔案本身存在問題。使用chardet庫檢測並指定正確的編碼,或檢查字幕檔案是否完整和正確。

錯誤3:腳本運行後無反應或崩潰

請檢查以下幾點:

  • Python環境是否正確安裝。
  • 所有必要的庫(pysrt, chardet)是否已安裝。
  • 字幕檔案路徑是否正確,且檔案存在。

進一步的優化建議

自動時間範圍識別

利用自然語言處理(NLP)技術,根據字幕內容自動識別並選擇需要保留的時間範圍。例如,保留特定主題或關鍵詞相關的字幕。

支持更多字幕格式

拓展腳本功能,支持其他字幕格式如.ass、vtt等,提升其通用性和適用範圍。

提升用戶介面友好度

通過添加圖形用戶界面(GUI),使操作更加直觀,特別適合不熟悉命令行的用戶。


結語

掌握如何使用Python處理字幕檔案,特別是過濾指定時間段的字幕,是視頻編輯和多媒體內容製作中的一項重要技能。希望本文提供的腳本和詳細解析能夠幫助您高效地完成這一任務,提升工作效率。


Last updated January 19, 2025
Search Again