图片测试

风景图

文字测试

https://xiaofan-blog-site.oss-cn-beijing.aliyuncs.com/img/20260708173154639.png

代码测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

import sys
from datetime import timedelta
from pathlib import Path
from faster_whisper import WhisperModel

# ============ 配置变量(按需修改)============
MODEL_SIZE = "small" # 模型大小: tiny/base/small/medium/large-v3
LANGUAGE = "zh" # 语言: zh / ja / en / None(自动检测)
DEVICE = "auto" # "auto" / "cpu" / "cuda"
COMPUTE_TYPE = "default" # "default" / "float16" / "int8" / "int8_float16"

INPUT_DIR = r"G:\audio\mp3" # MP3 文件所在目录
OUTPUT_DIR = r"G:\audio\md" # 输出 Markdown 文件目录
# ===========================================

def _format_timestamp(seconds: float) -> str:
"""把秒数格式化为 HH:MM:SS 形式"""
td = timedelta(seconds=seconds)
total_seconds = int(td.total_seconds())
hours, remainder = divmod(total_seconds, 3600)
minutes, secs = divmod(remainder, 60)
return f"{hours:02d}:{minutes:02d}:{secs:02d}"


def transcribe_mp3(model: WhisperModel, mp3_path: Path, output_dir: Path) -> bool:
"""转写单个 mp3 文件,输出 .md (Markdown) 文件"""
try:
print(f" 正在转写: {mp3_path.name} ... ", end="")
segments, info = model.transcribe(
str(mp3_path),
language=LANGUAGE,
beam_size=5,
)

md_path = output_dir / f"{mp3_path.stem}.md"
duration = round(info.duration, 2)
detected_lang = info.language

with open(md_path, "w", encoding="utf-8") as f:
# 文件头:标题与元信息
f.write(f"# {mp3_path.stem}\n\n")
f.write(f"- **文件名**: `{mp3_path.name}`\n")
f.write(f"- **语言**: {detected_lang}\n")
f.write(f"- **时长**: {duration}s({_format_timestamp(duration)})\n\n")
f.write("---\n\n")
# 正文:带时间戳的转写段落
for segment in segments:
start_ts = _format_timestamp(segment.start)
text = segment.text.strip()
if not text:
continue
f.write(f"**[{start_ts}]** {text}\n\n")

print(f"完成 (音频 {duration}s)")
return True
except Exception as e:
print(f"失败: {e}")
return False


def main():
input_dir = Path(INPUT_DIR)
output_dir = Path(OUTPUT_DIR)

# 检查输入目录
if not input_dir.is_dir():
print(f"错误: 输入目录不存在 -> {input_dir}")
sys.exit(1)

# 创建输出目录
output_dir.mkdir(parents=True, exist_ok=True)

# 收集所有 mp3 文件
mp3_files = sorted(input_dir.glob("*.mp3"))
if not mp3_files:
print(f"在 {input_dir} 中未找到任何 .mp3 文件")
return

print(f"找到 {len(mp3_files)} 个 MP3 文件")
print(f"正在加载模型: {MODEL_SIZE} ...")

# 加载模型
model = WhisperModel(
MODEL_SIZE,
device=DEVICE,
compute_type=COMPUTE_TYPE,
)

print("模型加载完成,开始转写...\n")

# 逐个转写
success = 0
fail = 0
for mp3 in mp3_files:
ok = transcribe_mp3(model, mp3, output_dir)
if ok:
success += 1
else:
fail += 1

# 汇总
print(f"\n{'='*40}")
print(f"全部完成! 成功: {success}, 失败: {fail}")
print(f"输出目录: {output_dir}")


if __name__ == "__main__":
main()