如何将带时间戳的视频转录文本智能分割为主题章节?
带时间戳转录文本的主题章节分割实现方案
以下是针对需求的三种可行Python实现方案,可直接处理带时间戳的文本列表,生成类似YouTube自动章节的主题分割结果:
方案一:Text Tiling 主题分割(轻量高效)
Text Tiling 通过计算相邻文本块的词汇重叠度识别主题边界,适合结构清晰的短/中等长度转录内容。
实现步骤
- 文本预处理:对每个带时间戳的文本条目做分词、去停用词、标准化(小写、去标点)。
- 滑动窗口相似度计算:按时间顺序将文本划分为固定大小的窗口,计算相邻窗口的词汇相似度(余弦相似度/Jaccard系数)。
- 分割点检测:定位相似度局部最小值的位置,结合阈值过滤误判,最终映射回时间戳生成章节。
代码示例
import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity def text_tiling_chapters(transcript_list, window_size=3, threshold=0.3): """ transcript_list: 格式为 [(start_time, end_time, text), ...],需按时间顺序排列 """ # 提取文本内容 texts = [item[2] for item in transcript_list] # TF-IDF向量化 tfidf = TfidfVectorizer(stop_words='english') tfidf_matrix = tfidf.fit_transform(texts) # 计算相邻窗口的平均相似度 similarities = [] for i in range(len(texts) - window_size): window1 = tfidf_matrix[i:i+window_size].mean(axis=0) window2 = tfidf_matrix[i+1:i+1+window_size].mean(axis=0) sim = cosine_similarity(window1, window2)[0][0] similarities.append(sim) # 检测符合条件的分割点 split_indices = [] for i in range(1, len(similarities)-1): if (similarities[i] < similarities[i-1] and similarities[i] < similarities[i+1] and similarities[i] < threshold): split_indices.append(i + window_size // 2) # 生成章节数据 chapters = [] start_idx = 0 for idx in split_indices + [len(texts)]: chapter_start = transcript_list[start_idx][0] chapter_end = transcript_list[idx-1][1] # 提取章节核心关键词作为标题 chapter_text = " ".join([t[2] for t in transcript_list[start_idx:idx]]) tfidf_chapter = tfidf.transform([chapter_text]) top_words = sorted(tfidf.vocabulary_.items(), key=lambda x: tfidf_chapter[0, x[1]], reverse=True)[:3] chapter_title = ", ".join([word for word, _ in top_words]) chapters.append({ "title": chapter_title, "start_time": chapter_start, "end_time": chapter_end }) start_idx = idx return chapters
方案二:时序主题建模(处理长文本主题演化)
针对长视频转录内容,使用支持时序约束的主题模型捕捉主题随时间的变化,进而生成章节。推荐用BERTopic,它结合了Transformer语义理解能力与时序主题建模功能。
实现步骤
- 数据整理:将每个带时间戳的文本条目作为独立文档,按时间顺序排列,提取时间戳作为时序特征。
- 训练时序主题模型:传入时间戳参数,让模型学习不同时间段的主题分布。
- 提取主题突变点:当相邻文档的主题分布差异超过阈值时,标记为章节分割点,映射回时间戳。
代码示例
from bertopic import BERTopic from bertopic.backend import TransformersBackend def bertopic_temporal_chapters(transcript_list): """ transcript_list: 格式为 [(start_time, end_time, text), ...],需按时间顺序排列 """ # 提取文本和数值型时间戳(如秒数) texts = [item[2] for item in transcript_list] timestamps = [item[0] for item in transcript_list] # 初始化带Transformer后端的BERTopic backend = TransformersBackend("all-MiniLM-L6-v2") topic_model = BERTopic( embedding_model=backend, nr_topics="auto", calculate_probabilities=True ) # 训练时序主题模型 topics, probabilities = topic_model.fit_transform(texts, timestamps) # 检测主题变化点 split_indices = [] prev_topic = topics[0] for i in range(1, len(topics)): if topics[i] != prev_topic and probabilities[i][topics[i]] > 0.7: split_indices.append(i) prev_topic = topics[i] # 生成章节数据 chapters = [] start_idx = 0 for idx in split_indices + [len(texts)]: chapter_start = transcript_list[start_idx][0] chapter_end = transcript_list[idx-1][1] # 获取章节主题作为标题 topic_id = topics[start_idx] chapter_title = topic_model.get_topic(topic_id)[0][0] if topic_id != -1 else "其他内容" chapters.append({ "title": chapter_title, "start_time": chapter_start, "end_time": chapter_end }) start_idx = idx return chapters
方案三:语义相似度分割(高精度语义理解)
使用预训练Transformer模型(如Sentence-BERT)计算相邻文本块的语义相似度,识别语义断层作为章节边界,适合复杂、歧义性高的转录内容。
实现步骤
- 生成语义嵌入:用Sentence-BERT为每个文本条目生成语义向量。
- 计算相似度:计算相邻向量的余弦相似度。
- 分割点筛选:设定相似度阈值,低于阈值且为局部最小值的位置作为章节分割点。
代码示例
from sentence_transformers import SentenceTransformer, util def semantic_similarity_chapters(transcript_list, threshold=0.6): """ transcript_list: 格式为 [(start_time, end_time, text), ...],需按时间顺序排列 """ # 加载轻量Sentence-BERT模型 model = SentenceTransformer('all-MiniLM-L6-v2') # 生成文本语义嵌入 texts = [item[2] for item in transcript_list] embeddings = model.encode(texts, convert_to_tensor=True) # 计算相邻文本的语义相似度 similarities = [] for i in range(len(embeddings)-1): sim = util.cos_sim(embeddings[i], embeddings[i+1]).item() similarities.append(sim) # 检测符合条件的分割点 split_indices = [] for i in range(1, len(similarities)-1): if (similarities[i] < similarities[i-1] and similarities[i] < similarities[i+1] and similarities[i] < threshold): split_indices.append(i+1) # 生成章节数据 chapters = [] start_idx = 0 for idx in split_indices + [len(texts)]: chapter_start = transcript_list[start_idx][0] chapter_end = transcript_list[idx-1][1] # 用章节开头第一句核心内容作为标题 chapter_title = transcript_list[start_idx][2].split('.')[0] if transcript_list[start_idx][2] else "未命名章节" chapters.append({ "title": chapter_title, "start_time": chapter_start, "end_time": chapter_end }) start_idx = idx return chapters
方案选择建议
- 短视频/结构清晰内容:优先选Text Tiling,计算快、资源消耗低。
- 长视频/主题演化明显内容:选时序BERTopic,能捕捉长期主题变化。
- 复杂内容/语义歧义高:选语义相似度分割,精度更高。
内容的提问来源于stack exchange,提问作者nonsequiter
相关产品推荐
相关产品推荐

