[.py] Auto extract/segment movie transcr ...

[.py] Auto extract/segment movie transcripts

Sep 05, 2025

import os

import re

import glob

import openai

import numpy as np

import whisper

# 指定 ffmpeg 的執行檔路徑

os.environ["PATH"] += os.pathsep + "/opt/homebrew/bin"

# 設定 OpenAI API 金鑰(請確認環境變數或直接指定)

openai.api_key ="xxx"

#############################################

# A. 透過 OpenAI Whisper 轉錄影片與 MP3 檔案

#############################################

def get_movie_transcript(video_file):

    """

    使用 OpenAI Whisper 模型對 MP4 影片進行語音轉錄,

    返回電影逐字稿(整個文字字串)。

    """

    print(f"開始轉錄影片:{video_file} ...")

    model = whisper.load_model("base")

    result = model.transcribe(video_file)

    transcript = result["text"].strip()

    print("影片轉錄完成。")

    return transcript

def extract_number(filename):

    """

    從檔名中提取數字部分,用於排序。

    假設檔名格式為 segment_1.mp3, segment_2.mp3, ...

    """

    base = os.path.basename(filename)

    m = re.search(r'(\d+)', base)

    if m:

        return int(m.group(1))

    return 0

def get_script_text_from_folder(folder):

    """

    從指定資料夾中讀取所有 MP3 檔案,

    按照檔名中數字部分排序後,分別使用 Whisper 模型轉錄,

    將所有轉錄結果合併成一個大字串(以換行分隔)。

    """

    mp3_files = sorted(glob.glob(os.path.join(folder, "*.mp3")), key=extract_number)

    if not mp3_files:

        print("指定資料夾中找不到 MP3 檔案!")

        return ""

    print(f"共找到 {len(mp3_files)} 個 MP3 檔案,開始轉錄...")

    model = whisper.load_model("base")

    all_text = []

    for mp3_file in mp3_files:

        print(f"轉錄 {mp3_file} ...")

        result = model.transcribe(mp3_file)

        text = result["text"].strip()

        all_text.append(text)

    script_text = "\n".join(all_text)

    print("所有 MP3 檔案轉錄完成。")

    return script_text

#############################################

# B. 文本拆分與匹配(參考之前的範例)

#############################################

def split_text(text):

    """

    利用正則表達式以中文、英文逗號、句號以及換行符拆分文本,

    並去除空白字串。

    """

    segments = re.split(r'[,,。.\n]', text)

    segments = [seg.strip() for seg in segments if seg.strip()]

    return segments

#############################################

# 2. 批次取得 OpenAI 嵌入向量(更新後)

#############################################

def get_embeddings_batch(texts, model="text-embedding-ada-002"):

    """

    使用 OpenAI API 的新版本接口一次取得多個文本的嵌入向量,

    返回一個 numpy array 列表。

    """

    response = openai.embeddings.create(input=texts, model=model)

    embeddings = [np.array(item.embedding) for item in response.data]

    return embeddings

#############################################

# 3. 計算 Cosine 相似度

#############################################

def cosine_similarity(vec1, vec2):

    """

    計算兩個向量之間的 cosine 相似度。

    """

    return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2) + 1e-8)

#############################################

# 4. 對應講稿段落與電影逐字稿段落

#############################################

def match_script_to_movie(script_segments, movie_segments, script_embeddings, movie_embeddings):

    """

    對每個講稿段落找出電影逐字稿中最相關的段落,

    返回一個列表,每項包含講稿段落、最佳匹配的電影段落、相似度分數及電影段落索引。

    """

    mapping = []

    for i, script_emb in enumerate(script_embeddings):

        best_score = -1

        best_index = None

        for j, movie_emb in enumerate(movie_embeddings):

            score = cosine_similarity(script_emb, movie_emb)

            if score > best_score:

                best_score = score

                best_index = j

        mapping.append({

            "script": script_segments[i],

            "movie": movie_segments[best_index],

            "score": best_score,

            "movie_index": best_index

        })

    return mapping

#############################################

# C. 主程式:取得影片逐字稿與講稿、拆分並匹配

#############################################

if __name__ == "__main__":

    # 請分別設定你的影片檔案與存放 MP3 檔的資料夾

    video_file = "Documents/Dallas_imovie.mp4"              # 例如:./videos/input.mp4

    mp3_folder = "Documents/2025-02-27_12-17-38"      # 例如:./scripts/,內含 segment_1.mp3, segment_2.mp3, 等

    # 1. 透過 Whisper 轉錄取得電影逐字稿

    movie_transcript = get_movie_transcript(video_file)

    # 2. 從指定資料夾中讀取所有 MP3 檔並轉錄,合併成講稿

    script_text = get_script_text_from_folder(mp3_folder)

    

    print("\n=== 取得的電影逐字稿 ===")

    print(movie_transcript)

    print("\n=== 取得的講稿 ===")

    print(script_text)

    

    # 3. 拆分文本:將電影逐字稿與講稿拆分成段落(或句子組)

    movie_segments = split_text(movie_transcript)

    script_segments = split_text(script_text)

    

    print("\n=== 電影逐字稿拆分結果 ===")

    for i, seg in enumerate(movie_segments, start=1):

        print(f"段落 {i}: {seg}")

    

    print("\n=== 講稿拆分結果 ===")

    for i, seg in enumerate(script_segments, start=1):

        print(f"講稿段落 {i}: {seg}")

    

    # 4. 使用 OpenAI API 批次取得嵌入

    print("\n取得電影逐字稿嵌入...")

    movie_embeddings = get_embeddings_batch(movie_segments)

    print("取得講稿嵌入...")

    script_embeddings = get_embeddings_batch(script_segments)

    

    # 5. 進行語意匹配

    mapping = match_script_to_movie(script_segments, movie_segments, script_embeddings, movie_embeddings)

    

    print("\n=== 講稿與電影逐字稿對應結果 ===")

    for item in mapping:

        print(f"講稿段落:{item['script']}")

        print(f"最佳匹配電影段落:{item['movie']} (索引: {item['movie_index']})")

        print(f"相似度分數:{item['score']:.3f}")

        print("-----------")

¿Te gusta esta publicación?

Comprar KVN CK L un libro

Más de KVN CK L