Initial commit for TTS project
This commit is contained in:
75
podcast_audios/PROJECT_STRUCTURE.md
Normal file
75
podcast_audios/PROJECT_STRUCTURE.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# 播客项目文件结构
|
||||
|
||||
所有播客项目按文件夹分类,每个项目一个独立文件夹。
|
||||
|
||||
## 📁 项目文件夹说明
|
||||
|
||||
### 1. project_belgrade/ (贝尔格莱德播客)
|
||||
- **描述**: 关于贝尔格莱德主题的对话播客
|
||||
- **文件**: 10个文件
|
||||
- `belgrade_ben_01-04.wav` - Ben的4段录音
|
||||
- `belgrade_judy_01-05.wav` - Judy的5段录音
|
||||
- `belgrade_podcast_judy_host.mp3` - 最终合成的播客
|
||||
|
||||
### 2. project_chapter8_demo/ (第8章MOSS-TTSD演示)
|
||||
- **描述**: 第8章内容的MOSS-TTSD语音克隆演示
|
||||
- **文件**: 4个文件
|
||||
- `chapter8_english_demo.wav` - 2分12秒的英文对话音频
|
||||
- `chapter8_english_demo.srt` - 同步字幕文件
|
||||
- `config/player_demo.html` - 交互式播放器页面
|
||||
- `config/test_player.html` - 测试播放器
|
||||
- `config/README_DEMO.txt` - 使用说明
|
||||
- `config/start_player.sh` - 启动脚本
|
||||
|
||||
### 3. project_multiguest/ (多嘉宾播客项目)
|
||||
- **描述**: 多嘉宾对话播客(Dmitri和Priya作为嘉宾)
|
||||
- **文件**: 34个文件
|
||||
- `multi_guest_callin_podcast.mp3/.srt` - 最终合成播客
|
||||
- `guest1_dmitri_*.mp3/.srt` - Dmitri的片段(6个文件)
|
||||
- `guest2_priya_*.mp3/.srt` - Priya的片段(6个文件)
|
||||
- `host1_alex_*.mp3/.srt` - Alex的片段(8个文件)
|
||||
- `host2_sarah_*.mp3/.srt` - Sarah的片段(12个文件)
|
||||
|
||||
### 4. project_dmitri/ (Dmitri声音样本)
|
||||
- **描述**: Dmitri的俄语口音声音样本
|
||||
- **文件**: 6个文件
|
||||
- `russian_dmitri.mp3/.srt` - 原始版本
|
||||
- `russian_dmitri_balanced.mp3/.srt` - 平衡版本
|
||||
- `russian_dmitri_light.mp3/.srt` - 轻量版本
|
||||
|
||||
### 5. project_priya/ (Priya声音样本)
|
||||
- **描述**: Priya的印度口音声音样本
|
||||
- **文件**: 4个文件
|
||||
- `indian_priya.mp3/.srt` - 原始版本
|
||||
- `indian_priya_intense.mp3/.srt` - 强烈版本
|
||||
|
||||
### 6. project_sophie/ (Sophie声音样本)
|
||||
- **描述**: Sophie的英国口音声音样本
|
||||
- **文件**: 2个文件
|
||||
- `british_sophie.mp3/.srt`
|
||||
|
||||
## 🎯 使用建议
|
||||
|
||||
### 当前活跃项目
|
||||
- **project_chapter8_demo**: 最新的MOSS-TTSD演示项目
|
||||
- 可直接运行: `cd project_chapter8_demo && python3 -m http.server 8080`
|
||||
- 访问: `http://your-ip:8080/config/player_demo.html`
|
||||
|
||||
### 归档项目
|
||||
其他项目为早期测试或素材文件,可按需保留或删除。
|
||||
|
||||
## 🗑️ 可删除文件(如果不需要)
|
||||
|
||||
如果磁盘空间紧张,可以删除:
|
||||
- `project_dmitri/` - 仅保留一个版本即可
|
||||
- `project_priya/` - 仅保留一个版本即可
|
||||
- `project_sophie/` - 测试文件
|
||||
- `project_belgrade/` - 早期测试
|
||||
- `project_multiguest/` - 保留最终mp3即可,删除片段文件
|
||||
|
||||
## 📊 磁盘使用情况
|
||||
|
||||
总大小约: 21MB
|
||||
- project_multiguest: 约 15MB (最大)
|
||||
- project_chapter8_demo: 约 7.7MB
|
||||
- 其他项目: 约 2MB
|
||||
82
podcast_audios/cleanup.sh
Executable file
82
podcast_audios/cleanup.sh
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 清理播客项目文件夹
|
||||
# 删除不需要的测试文件和重复版本
|
||||
|
||||
echo "🧹 开始清理播客项目文件夹..."
|
||||
echo "================================"
|
||||
|
||||
# 确认提示
|
||||
read -p "确定要清理测试文件吗? (y/n): " confirm
|
||||
if [ "$confirm" != "y" ]; then
|
||||
echo "取消清理"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 统计清理前的大小
|
||||
before_size=$(du -sh /root/tts/podcast_audios | cut -f1)
|
||||
echo "清理前大小: $before_size"
|
||||
echo ""
|
||||
|
||||
# 1. 删除项目中的重复声音样本(保留一个版本)
|
||||
echo "1. 清理重复的声音样本..."
|
||||
|
||||
# 在 project_dmitri 中只保留原始版本
|
||||
if [ -d "project_dmitri" ]; then
|
||||
cd project_dmitri
|
||||
rm -f russian_dmitri_balanced.* russian_dmitri_light.*
|
||||
echo " - Dmitri: 保留原始版本,删除balanced和light版本"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# 在 project_priya 中只保留原始版本
|
||||
if [ -d "project_priya" ]; then
|
||||
cd project_priya
|
||||
rm -f indian_priya_intense.*
|
||||
echo " - Priya: 保留原始版本,删除intense版本"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# 2. 删除测试项目(如果不需要)
|
||||
echo ""
|
||||
echo "2. 删除早期测试项目..."
|
||||
rm -rf project_sophie project_belgrade
|
||||
echo " - 删除: project_sophie (英国口音测试)"
|
||||
echo " - 删除: project_belgrade (贝尔格莱德测试)"
|
||||
|
||||
# 3. 删除多嘉宾项目的片段文件(只保留最终合成版)
|
||||
echo ""
|
||||
echo "3. 清理多嘉宾项目片段文件..."
|
||||
if [ -d "project_multiguest" ]; then
|
||||
cd project_multiguest
|
||||
# 保留最终合成文件
|
||||
mkdir -p ../temp_multiguest
|
||||
cp multi_guest_callin_podcast.mp3 multi_guest_callin_podcast.srt ../temp_multiguest/
|
||||
# 删除所有片段
|
||||
cd ..
|
||||
rm -rf project_multiguest
|
||||
mv temp_multiguest project_multiguest
|
||||
echo " - 多嘉宾项目: 只保留最终合成版,删除39个片段文件"
|
||||
fi
|
||||
|
||||
# 4. 删除MOSS-TTSD演示项目中的测试文件
|
||||
echo ""
|
||||
echo "4. 清理MOSS-TTSD演示项目..."
|
||||
if [ -d "project_chapter8_demo" ]; then
|
||||
cd project_chapter8_demo/config
|
||||
rm -f test_player.html
|
||||
echo " - 删除测试播放器文件"
|
||||
cd ../..
|
||||
fi
|
||||
|
||||
echo ""
|
||||
# 统计清理后的大小
|
||||
after_size=$(du -sh /root/tts/podcast_audios | cut -f1)
|
||||
echo "清理后大小: $after_size"
|
||||
echo ""
|
||||
echo "✅ 清理完成!"
|
||||
echo ""
|
||||
echo "剩余项目:"
|
||||
ls -d project_*
|
||||
echo ""
|
||||
echo "说明文件: PROJECT_STRUCTURE.md"
|
||||
BIN
podcast_audios/project_belgrade/belgrade_ben_01.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_ben_01.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_ben_02.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_ben_02.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_ben_03.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_ben_03.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_ben_04.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_ben_04.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_judy_01.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_judy_01.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_judy_02.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_judy_02.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_judy_03.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_judy_03.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_judy_04.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_judy_04.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_judy_05.wav
Normal file
BIN
podcast_audios/project_belgrade/belgrade_judy_05.wav
Normal file
Binary file not shown.
BIN
podcast_audios/project_belgrade/belgrade_podcast_judy_host.mp3
Normal file
BIN
podcast_audios/project_belgrade/belgrade_podcast_judy_host.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,71 @@
|
||||
1
|
||||
00:00:00,000 --> 00:00:03,500
|
||||
[S1] Today we're discussing Tom Clancy. A thriller writer, yet called by the author the most underrated geopolitical analyst in American history.
|
||||
|
||||
2
|
||||
00:00:03,500 --> 00:00:05,200
|
||||
[S2] That's a bold claim. Tell me more.
|
||||
|
||||
3
|
||||
00:00:05,200 --> 00:00:09,800
|
||||
[S1] His 2000 novel 'The Bear and the Dragon' predicted the 2022 Russia-Ukraine war and the China-Russia 'no-limits' alliance, 22 years in advance.
|
||||
|
||||
4
|
||||
00:00:09,800 --> 00:00:12,500
|
||||
[S1] How did a guy writing airport novels in Maryland see more clearly than the entire CIA?
|
||||
|
||||
5
|
||||
00:00:12,500 --> 00:00:16,200
|
||||
[S2] This isn't just prediction, it's simulation. He built Soviet naval strategy models so accurate that the Pentagon invited him to wargame with generals.
|
||||
|
||||
6
|
||||
00:00:16,200 --> 00:00:19,000
|
||||
[S2] He understood one key thing: war is a system, not an event.
|
||||
|
||||
7
|
||||
00:00:19,000 --> 00:00:23,500
|
||||
[S1] 'The Hunt for Red October' is a primer on submarine acoustics. 'Clear and Present Danger' explains drug cartels and congressional oversight.
|
||||
|
||||
8
|
||||
00:00:23,500 --> 00:00:26,000
|
||||
[S1] But 'The Bear and the Dragon' is truly scary.
|
||||
|
||||
9
|
||||
00:00:26,000 --> 00:00:30,500
|
||||
[S2] In the book, China and Russia form a military alliance, invade Alaska, catch America off-guard, paralyze NATO.
|
||||
|
||||
10
|
||||
00:00:30,500 --> 00:00:34,800
|
||||
[S2] But here's the brilliant part: the war doesn't end in nuclear apocalypse. It ends in ceasefire and a new Cold War stalemate.
|
||||
|
||||
11
|
||||
00:00:34,800 --> 00:00:39,200
|
||||
[S1] In 2022, China and Russia didn't invade Alaska, but they did form a 'no-limits' alliance that caught the West off-guard.
|
||||
|
||||
12
|
||||
00:00:39,200 --> 00:00:41,000
|
||||
[S1] Why was Clancy right?
|
||||
|
||||
13
|
||||
00:00:41,000 --> 00:00:45,500
|
||||
[S2] Because he understood the mathematics of power. When China's economy became 10 times Russia's, the math changed.
|
||||
|
||||
14
|
||||
00:00:45,500 --> 00:00:49,000
|
||||
[S2] Russia could no longer be a peer player, it had to become a junior partner. This isn't ideology, it's arithmetic.
|
||||
|
||||
15
|
||||
00:00:49,000 --> 00:00:54,500
|
||||
[S1] The scariest part: when Clancy wrote the book, China's GDP was still smaller than Italy's. Everyone thought he was crazy.
|
||||
|
||||
16
|
||||
00:00:54,500 --> 00:00:58,000
|
||||
[S1] But he saw the trajectory. He saw that the 21st century would be Asian.
|
||||
|
||||
17
|
||||
00:00:58,000 --> 00:01:02,500
|
||||
[S2] China had two choices: dominate its neighbors or merge with them. China chose to merge. Russia had no choice.
|
||||
|
||||
18
|
||||
00:01:02,500 --> 00:01:06,800
|
||||
[S2] That's why Clancy isn't a novelist, he's an analyst. He read the same data as everyone else, but he knew how to read it for blood.
|
||||
BIN
podcast_audios/project_chapter8_demo/chapter8_english_demo.wav
Normal file
BIN
podcast_audios/project_chapter8_demo/chapter8_english_demo.wav
Normal file
Binary file not shown.
66
podcast_audios/project_chapter8_demo/config/README_DEMO.txt
Normal file
66
podcast_audios/project_chapter8_demo/config/README_DEMO.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
MOSS-TTSD Podcast Player Demo - 使用说明
|
||||
=========================================
|
||||
|
||||
📁 文件清单:
|
||||
-----------
|
||||
1. player_demo.html - HTML播放器页面
|
||||
2. chapter8_english_demo.wav - 音频文件 (2分12秒)
|
||||
3. chapter8_english_demo.srt - 字幕文件
|
||||
4. start_player.sh - 启动脚本
|
||||
|
||||
🎯 功能特点:
|
||||
----------
|
||||
✅ 音频播放控制 (播放/暂停)
|
||||
✅ 字幕实时高亮显示
|
||||
✅ 说话人头像状态同步 (谁说话谁亮)
|
||||
✅ 点击字幕跳转播放位置
|
||||
✅ 响应式设计 (支持手机/平板)
|
||||
|
||||
🚀 使用方法:
|
||||
----------
|
||||
方法1: 一键启动
|
||||
bash /root/tts/podcast_audios/start_player.sh
|
||||
|
||||
方法2: 手动启动
|
||||
cd /root/tts/podcast_audios
|
||||
python3 -m http.server 8080
|
||||
|
||||
访问地址:
|
||||
http://100.116.162.71:8080/player_demo.html
|
||||
|
||||
📝 演示内容:
|
||||
----------
|
||||
主题: 汤姆·克兰西的地缘政治预言
|
||||
对话角色:
|
||||
- S1 (主持人): 你的声音 (ben_guanquelou.wav)
|
||||
- S2 (嘉宾): Judy的声音 (judy_dalingtaohua_trim.wav)
|
||||
|
||||
技术亮点:
|
||||
- 零样本声音克隆
|
||||
- 2分钟+连续对话生成
|
||||
- 角色音色区分清晰
|
||||
- 自然对话节奏
|
||||
|
||||
📱 移动端访问:
|
||||
------------
|
||||
在手机浏览器输入相同地址,自动适配竖屏布局
|
||||
|
||||
🎧 音频验证:
|
||||
----------
|
||||
文件位置: /root/tts/podcast_audios/chapter8_english_demo.wav
|
||||
文件大小: 8.1MB
|
||||
音频时长: 2分12秒
|
||||
|
||||
命令验证:
|
||||
ffprobe chapter8_english_demo.wav 2>&1 | grep Duration
|
||||
|
||||
🔄 重新生成:
|
||||
----------
|
||||
如果需要重新生成音频:
|
||||
cd /root/tts/MOSS-TTSD
|
||||
python generate_chapter8_demo.py
|
||||
|
||||
💡 自定义对话:
|
||||
------------
|
||||
编辑文件: chapter8_english_script.txt
|
||||
运行: python generate_moss_ttsd_podcast.py chapter8_english_script.txt my_demo
|
||||
565
podcast_audios/project_chapter8_demo/config/player_demo.html
Normal file
565
podcast_audios/project_chapter8_demo/config/player_demo.html
Normal file
@@ -0,0 +1,565 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MOSS-TTSD Podcast Player - Chapter 8 Demo</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
height: 90vh;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.main-area {
|
||||
padding: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2em;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.header .subtitle {
|
||||
font-size: 1.1em;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.avatars-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 60px;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.avatar-circle {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 4px solid transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 3em;
|
||||
margin: 0 auto 15px;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar.s1 .avatar-circle {
|
||||
background: linear-gradient(135deg, rgba(135, 206, 235, 0.3), rgba(70, 130, 180, 0.5));
|
||||
}
|
||||
|
||||
.avatar.s2 .avatar-circle {
|
||||
background: linear-gradient(135deg, rgba(152, 251, 152, 0.3), rgba(50, 205, 50, 0.5));
|
||||
}
|
||||
|
||||
.avatar.active .avatar-circle {
|
||||
border-color: #ffd700;
|
||||
box-shadow: 0 0 30px rgba(255, 215, 0, 0.6);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.avatar.speaking::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: -10px;
|
||||
right: -10px;
|
||||
bottom: -10px;
|
||||
background: radial-gradient(circle, rgba(255, 215, 0, 0.3) 0%, transparent 70%);
|
||||
border-radius: 50%;
|
||||
animation: pulse 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(0.8); opacity: 1; }
|
||||
50% { transform: scale(1.2); opacity: 0.5; }
|
||||
100% { transform: scale(0.8); opacity: 1; }
|
||||
}
|
||||
|
||||
.avatar-name {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.avatar-role {
|
||||
font-size: 0.9em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.audio-player-container {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.audio-player {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.control-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.control-btn.playing {
|
||||
background: #4caf50;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
padding: 30px 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 20px;
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.subtitle-line {
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
border-radius: 10px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-left: 4px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subtitle-line:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.subtitle-line.active {
|
||||
border-left-color: #ffd700;
|
||||
background: rgba(255, 215, 0, 0.15);
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.subtitle-line.s1 {
|
||||
border-left-color: #87ceeb;
|
||||
}
|
||||
|
||||
.subtitle-line.s2 {
|
||||
border-left-color: #98fb98;
|
||||
}
|
||||
|
||||
.subtitle-line.s1.active {
|
||||
border-left-color: #ffd700;
|
||||
}
|
||||
|
||||
.subtitle-line.s2.active {
|
||||
border-left-color: #ffd700;
|
||||
}
|
||||
|
||||
.speaker-label {
|
||||
font-weight: bold;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.subtitle-line.s1 .speaker-label {
|
||||
color: #87ceeb;
|
||||
}
|
||||
|
||||
.subtitle-line.s2 .speaker-label {
|
||||
color: #98fb98;
|
||||
}
|
||||
|
||||
.subtitle-text {
|
||||
line-height: 1.5;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.time-display {
|
||||
font-size: 0.8em;
|
||||
opacity: 0.7;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.loading::after {
|
||||
content: '';
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
border-top-color: #ffd700;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr auto;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
max-height: 40vh;
|
||||
}
|
||||
|
||||
.avatars-container {
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.avatar-circle {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="main-area">
|
||||
<div class="header">
|
||||
<h1>MOSS-TTSD Podcast Player</h1>
|
||||
<div class="subtitle">Chapter 8: Tom Clancy's Geopolitical Prophecy</div>
|
||||
</div>
|
||||
|
||||
<div class="avatars-container">
|
||||
<div class="avatar s1" id="avatar-s1">
|
||||
<div class="avatar-circle">🎤</div>
|
||||
<div class="avatar-name">Speaker 1</div>
|
||||
<div class="avatar-role">Host</div>
|
||||
</div>
|
||||
|
||||
<div class="avatar s2" id="avatar-s2">
|
||||
<div class="avatar-circle">🎙️</div>
|
||||
<div class="avatar-name">Speaker 2</div>
|
||||
<div class="avatar-role">Guest</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="audio-player-container">
|
||||
<audio id="audio-player" class="audio-player" controls>
|
||||
<source src="chapter8_english_demo.wav" type="audio/wav">
|
||||
Your browser does not support the audio element.
|
||||
</audio>
|
||||
|
||||
<div class="controls">
|
||||
<button id="play-btn" class="control-btn">▶️ Play</button>
|
||||
<button id="sync-btn" class="control-btn">🔄 Sync</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar">
|
||||
<h2>Dialogue Script</h2>
|
||||
<div id="subtitle-container">
|
||||
<div class="loading">Loading subtitles...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
class PodcastPlayer {
|
||||
constructor() {
|
||||
this.audio = document.getElementById('audio-player');
|
||||
this.playBtn = document.getElementById('play-btn');
|
||||
this.syncBtn = document.getElementById('sync-btn');
|
||||
this.subtitleContainer = document.getElementById('subtitle-container');
|
||||
this.avatarS1 = document.getElementById('avatar-s1');
|
||||
this.avatarS2 = document.getElementById('avatar-s2');
|
||||
|
||||
this.subtitles = [];
|
||||
this.currentSubtitleIndex = -1;
|
||||
this.isPlaying = false;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.loadSubtitles();
|
||||
this.setupEventListeners();
|
||||
this.renderSubtitles();
|
||||
}
|
||||
|
||||
async loadSubtitles() {
|
||||
try {
|
||||
const response = await fetch('chapter8_english_demo.srt');
|
||||
const srtText = await response.text();
|
||||
this.subtitles = this.parseSRT(srtText);
|
||||
} catch (error) {
|
||||
console.error('Failed to load subtitles:', error);
|
||||
// Fallback: generate dummy subtitles for demo
|
||||
this.subtitles = this.generateDummySubtitles();
|
||||
}
|
||||
}
|
||||
|
||||
parseSRT(srtText) {
|
||||
const subtitles = [];
|
||||
const blocks = srtText.trim().split('\n\n');
|
||||
|
||||
for (const block of blocks) {
|
||||
const lines = block.split('\n').filter(line => line.trim()); // 过滤空行
|
||||
if (lines.length >= 3) {
|
||||
const timeLine = lines[1];
|
||||
const textLines = lines.slice(2);
|
||||
|
||||
// 找到第一个非空且包含[S1]或[S2]的行
|
||||
const speakerLine = textLines.find(line => line.includes('[S1]') || line.includes('[S2]'));
|
||||
if (!speakerLine) continue;
|
||||
|
||||
const [startTime, endTime] = timeLine.split(' --> ');
|
||||
const speaker = speakerLine.includes('[S1]') ? 's1' : 's2';
|
||||
const text = speakerLine.replace(/\[S[12]\]\s*/, '');
|
||||
|
||||
subtitles.push({
|
||||
start: this.parseTime(startTime),
|
||||
end: this.parseTime(endTime),
|
||||
speaker: speaker,
|
||||
text: text
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return subtitles;
|
||||
}
|
||||
|
||||
generateDummySubtitles() {
|
||||
return [
|
||||
{ start: 0, end: 3.5, speaker: 's1', text: "Today we're discussing Tom Clancy. A thriller writer, yet called by the author the most underrated geopolitical analyst in American history." },
|
||||
{ start: 3.5, end: 5.2, speaker: 's2', text: "That's a bold claim. Tell me more." },
|
||||
{ start: 5.2, end: 9.8, speaker: 's1', text: "His 2000 novel 'The Bear and the Dragon' predicted the 2022 Russia-Ukraine war and the China-Russia 'no-limits' alliance, 22 years in advance." },
|
||||
{ start: 9.8, end: 12.5, speaker: 's1', text: "How did a guy writing airport novels in Maryland see more clearly than the entire CIA?" },
|
||||
{ start: 12.5, end: 16.2, speaker: 's2', text: "This isn't just prediction, it's simulation. He built Soviet naval strategy models so accurate that the Pentagon invited him to wargame with generals." },
|
||||
{ start: 16.2, end: 19.0, speaker: 's2', text: "He understood one key thing: war is a system, not an event." },
|
||||
{ start: 19.0, end: 23.5, speaker: 's1', text: "'The Hunt for Red October' is a primer on submarine acoustics. 'Clear and Present Danger' explains drug cartels and congressional oversight." },
|
||||
{ start: 23.5, end: 26.0, speaker: 's1', text: "But 'The Bear and the Dragon' is truly scary." },
|
||||
{ start: 26.0, end: 30.5, speaker: 's2', text: "In the book, China and Russia form a military alliance, invade Alaska, catch America off-guard, paralyze NATO." },
|
||||
{ start: 30.5, end: 34.8, speaker: 's2', text: "But here's the brilliant part: the war doesn't end in nuclear apocalypse. It ends in ceasefire and a new Cold War stalemate." },
|
||||
{ start: 34.8, end: 39.2, speaker: 's1', text: "In 2022, China and Russia didn't invade Alaska, but they did form a 'no-limits' alliance that caught the West off-guard." },
|
||||
{ start: 39.2, end: 41.0, speaker: 's1', text: "Why was Clancy right?" },
|
||||
{ start: 41.0, end: 45.5, speaker: 's2', text: "Because he understood the mathematics of power. When China's economy became 10 times Russia's, the math changed." },
|
||||
{ start: 45.5, end: 49.0, speaker: 's2', text: "Russia could no longer be a peer player, it had to become a junior partner. This isn't ideology, it's arithmetic." },
|
||||
{ start: 49.0, end: 54.5, speaker: 's1', text: "The scariest part: when Clancy wrote the book, China's GDP was still smaller than Italy's. Everyone thought he was crazy." },
|
||||
{ start: 54.5, end: 58.0, speaker: 's1', text: "But he saw the trajectory. He saw that the 21st century would be Asian." },
|
||||
{ start: 58.0, end: 62.5, speaker: 's2', text: "China had two choices: dominate its neighbors or merge with them. China chose to merge. Russia had no choice." },
|
||||
{ start: 62.5, end: 66.8, speaker: 's2', text: "That's why Clancy isn't a novelist, he's an analyst. He read the same data as everyone else, but he knew how to read it for blood." }
|
||||
];
|
||||
}
|
||||
|
||||
parseTime(timeStr) {
|
||||
const [time, ms] = timeStr.split(',');
|
||||
const [hours, minutes, seconds] = time.split(':');
|
||||
return parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds) + parseInt(ms) / 1000;
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
this.audio.addEventListener('timeupdate', () => {
|
||||
this.updateSubtitle();
|
||||
});
|
||||
|
||||
this.audio.addEventListener('play', () => {
|
||||
this.isPlaying = true;
|
||||
this.playBtn.textContent = '⏸️ Pause';
|
||||
this.playBtn.classList.add('playing');
|
||||
});
|
||||
|
||||
this.audio.addEventListener('pause', () => {
|
||||
this.isPlaying = false;
|
||||
this.playBtn.textContent = '▶️ Play';
|
||||
this.playBtn.classList.remove('playing');
|
||||
});
|
||||
|
||||
this.playBtn.addEventListener('click', () => {
|
||||
if (this.audio.paused) {
|
||||
this.audio.play();
|
||||
} else {
|
||||
this.audio.pause();
|
||||
}
|
||||
});
|
||||
|
||||
this.syncBtn.addEventListener('click', () => {
|
||||
this.syncSubtitles();
|
||||
});
|
||||
}
|
||||
|
||||
updateSubtitle() {
|
||||
const currentTime = this.audio.currentTime;
|
||||
const subtitleIndex = this.findSubtitleIndex(currentTime);
|
||||
|
||||
if (subtitleIndex !== this.currentSubtitleIndex) {
|
||||
console.log('Subtitle changed:', subtitleIndex, 'at time:', currentTime);
|
||||
this.currentSubtitleIndex = subtitleIndex;
|
||||
this.highlightSubtitle(subtitleIndex);
|
||||
this.updateAvatar(subtitleIndex >= 0 ? this.subtitles[subtitleIndex].speaker : null);
|
||||
}
|
||||
}
|
||||
|
||||
findSubtitleIndex(time) {
|
||||
for (let i = 0; i < this.subtitles.length; i++) {
|
||||
if (time >= this.subtitles[i].start && time < this.subtitles[i].end) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
highlightSubtitle(index) {
|
||||
// Remove previous active class
|
||||
const prevActive = document.querySelector('.subtitle-line.active');
|
||||
if (prevActive) {
|
||||
prevActive.classList.remove('active');
|
||||
}
|
||||
|
||||
// Add active class to current subtitle
|
||||
if (index >= 0) {
|
||||
const element = document.querySelector(`[data-subtitle-index="${index}"]`);
|
||||
if (element) {
|
||||
console.log('Highlighting subtitle:', index, element);
|
||||
element.classList.add('active');
|
||||
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
} else {
|
||||
console.error('Subtitle element not found for index:', index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateAvatar(speaker) {
|
||||
// Reset avatars
|
||||
this.avatarS1.classList.remove('active', 'speaking');
|
||||
this.avatarS2.classList.remove('active', 'speaking');
|
||||
|
||||
// Activate current speaker
|
||||
if (speaker === 's1') {
|
||||
console.log('Activating S1 avatar');
|
||||
this.avatarS1.classList.add('active', 'speaking');
|
||||
} else if (speaker === 's2') {
|
||||
console.log('Activating S2 avatar');
|
||||
this.avatarS2.classList.add('active', 'speaking');
|
||||
} else {
|
||||
console.log('No speaker active');
|
||||
}
|
||||
}
|
||||
|
||||
renderSubtitles() {
|
||||
this.subtitleContainer.innerHTML = '';
|
||||
|
||||
this.subtitles.forEach((subtitle, index) => {
|
||||
const lineElement = document.createElement('div');
|
||||
lineElement.className = `subtitle-line ${subtitle.speaker}`;
|
||||
lineElement.setAttribute('data-subtitle-index', index);
|
||||
|
||||
lineElement.innerHTML = `
|
||||
<div class="speaker-label">[${subtitle.speaker.toUpperCase()}]</div>
|
||||
<div class="subtitle-text">${subtitle.text}</div>
|
||||
<div class="time-display">${this.formatTime(subtitle.start)} - ${this.formatTime(subtitle.end)}</div>
|
||||
`;
|
||||
|
||||
lineElement.addEventListener('click', () => {
|
||||
this.audio.currentTime = subtitle.start;
|
||||
this.audio.play();
|
||||
});
|
||||
|
||||
this.subtitleContainer.appendChild(lineElement);
|
||||
});
|
||||
}
|
||||
|
||||
formatTime(seconds) {
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
syncSubtitles() {
|
||||
// Recalculate subtitle timings based on audio duration
|
||||
const audioDuration = this.audio.duration;
|
||||
if (audioDuration && this.subtitles.length > 0) {
|
||||
const subtitleDuration = audioDuration / this.subtitles.length;
|
||||
this.subtitles.forEach((subtitle, index) => {
|
||||
subtitle.start = index * subtitleDuration;
|
||||
subtitle.end = (index + 1) * subtitleDuration;
|
||||
});
|
||||
console.log('Subtitles synced to audio duration:', audioDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize player when page loads
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new PodcastPlayer();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
15
podcast_audios/project_chapter8_demo/config/start_player.sh
Normal file
15
podcast_audios/project_chapter8_demo/config/start_player.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎙️ MOSS-TTSD Podcast Player Demo"
|
||||
echo "================================"
|
||||
echo ""
|
||||
echo "📁 文件位置: /root/tts/podcast_audios/"
|
||||
echo "📄 HTML文件: player_demo.html"
|
||||
echo "🎵 音频文件: chapter8_english_demo.wav"
|
||||
echo "📝 字幕文件: chapter8_english_demo.srt"
|
||||
echo ""
|
||||
echo "🚀 启动HTTP服务器..."
|
||||
echo ""
|
||||
|
||||
cd /root/tts/podcast_audios
|
||||
python3 -m http.server 8080
|
||||
85
podcast_audios/project_chapter8_demo/config/test_player.html
Normal file
85
podcast_audios/project_chapter8_demo/config/test_player.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test Player</title>
|
||||
<style>
|
||||
body { font-family: Arial; padding: 20px; }
|
||||
.avatar { width: 100px; height: 100px; border: 3px solid gray; border-radius: 50%; display: inline-block; margin: 20px; text-align: center; line-height: 100px; }
|
||||
.avatar.active { border-color: gold; background: yellow; }
|
||||
.subtitle { padding: 10px; margin: 5px; background: #f0f0f0; }
|
||||
.subtitle.active { background: yellow; }
|
||||
.s1 { border-left: 5px solid blue; }
|
||||
.s2 { border-left: 5px solid green; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test Player</h1>
|
||||
|
||||
<div>
|
||||
<div class="avatar s1" id="avatar-s1">S1</div>
|
||||
<div class="avatar s2" id="avatar-s2">S2</div>
|
||||
</div>
|
||||
|
||||
<audio id="audio" controls>
|
||||
<source src="chapter8_english_demo.wav" type="audio/wav">
|
||||
</audio>
|
||||
|
||||
<div id="subtitle-container"></div>
|
||||
|
||||
<div id="debug" style="margin-top: 20px; padding: 10px; background: #eee;"></div>
|
||||
|
||||
<script>
|
||||
// 测试字幕数据
|
||||
const testSubtitles = [
|
||||
{ start: 0, end: 3, speaker: 's1', text: 'First subtitle from S1' },
|
||||
{ start: 3, end: 6, speaker: 's2', text: 'Second subtitle from S2' },
|
||||
{ start: 6, end: 9, speaker: 's1', text: 'Third subtitle from S1' }
|
||||
];
|
||||
|
||||
const audio = document.getElementById('audio');
|
||||
const container = document.getElementById('subtitle-container');
|
||||
const debug = document.getElementById('debug');
|
||||
let currentIndex = -1;
|
||||
|
||||
// 渲染字幕
|
||||
testSubtitles.forEach((sub, index) => {
|
||||
const div = document.createElement('div');
|
||||
div.className = `subtitle ${sub.speaker}`;
|
||||
div.textContent = `[${sub.speaker}] ${sub.text}`;
|
||||
div.dataset.index = index;
|
||||
container.appendChild(div);
|
||||
});
|
||||
|
||||
// 更新时间
|
||||
audio.addEventListener('timeupdate', () => {
|
||||
const time = audio.currentTime;
|
||||
const newIndex = testSubtitles.findIndex(sub => time >= sub.start && time < sub.end);
|
||||
|
||||
if (newIndex !== currentIndex) {
|
||||
currentIndex = newIndex;
|
||||
|
||||
// 清除之前的高亮
|
||||
document.querySelectorAll('.subtitle').forEach(s => s.classList.remove('active'));
|
||||
document.querySelectorAll('.avatar').forEach(a => a.classList.remove('active'));
|
||||
|
||||
if (newIndex >= 0) {
|
||||
// 高亮新的字幕和头像
|
||||
const subtitleEl = document.querySelector(`[data-index="${newIndex}"]`);
|
||||
if (subtitleEl) subtitleEl.classList.add('active');
|
||||
|
||||
const speaker = testSubtitles[newIndex].speaker;
|
||||
const avatarEl = document.getElementById(`avatar-${speaker}`);
|
||||
if (avatarEl) avatarEl.classList.add('active');
|
||||
|
||||
debug.innerHTML = `Time: ${time.toFixed(2)}s, Index: ${newIndex}, Speaker: ${speaker}`;
|
||||
} else {
|
||||
debug.innerHTML = `Time: ${time.toFixed(2)}s, No subtitle`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
debug.innerHTML = 'Ready. Press play to test.';
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
podcast_audios/project_dmitri/russian_dmitri.mp3
Normal file
BIN
podcast_audios/project_dmitri/russian_dmitri.mp3
Normal file
Binary file not shown.
16
podcast_audios/project_dmitri/russian_dmitri.srt
Normal file
16
podcast_audios/project_dmitri/russian_dmitri.srt
Normal file
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:06,050
|
||||
Your comparison of the Ukraine war to Turgenev's Fathers and Sons really hit home.
|
||||
|
||||
2
|
||||
00:00:06,000 --> 00:00:16,037
|
||||
You said Putin is the 'Father' fighting for Space (territory), while the youth in St. Petersburg are the 'Sons' who care about Time (the future).
|
||||
|
||||
3
|
||||
00:00:16,037 --> 00:00:21,262
|
||||
The 'Sons' are silent right now—'whispering on the Neva,' as you put it.
|
||||
|
||||
4
|
||||
00:00:21,262 --> 00:00:31,500
|
||||
My question is: In this tragic version of the story, do the Sons eventually inherit the house, or do the Fathers burn the house down before they die?
|
||||
|
||||
BIN
podcast_audios/project_dmitri/russian_dmitri_balanced.mp3
Normal file
BIN
podcast_audios/project_dmitri/russian_dmitri_balanced.mp3
Normal file
Binary file not shown.
16
podcast_audios/project_dmitri/russian_dmitri_balanced.srt
Normal file
16
podcast_audios/project_dmitri/russian_dmitri_balanced.srt
Normal file
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:06,050
|
||||
Your comparison of the Ukraine war to Turgenev's Fathers and Sons really hit home.
|
||||
|
||||
2
|
||||
00:00:06,000 --> 00:00:16,037
|
||||
You said Putin is the 'Father' fighting for Space (territory), while the youth in St. Petersburg are the 'Sons' who care about Time (the future).
|
||||
|
||||
3
|
||||
00:00:16,037 --> 00:00:21,262
|
||||
The 'Sons' are silent right now—'whispering on the Neva,' as you put it.
|
||||
|
||||
4
|
||||
00:00:21,262 --> 00:00:31,500
|
||||
My question is: In this tragic version of the story, do the Sons eventually inherit the house, or do the Fathers burn the house down before they die?
|
||||
|
||||
BIN
podcast_audios/project_dmitri/russian_dmitri_light.mp3
Normal file
BIN
podcast_audios/project_dmitri/russian_dmitri_light.mp3
Normal file
Binary file not shown.
16
podcast_audios/project_dmitri/russian_dmitri_light.srt
Normal file
16
podcast_audios/project_dmitri/russian_dmitri_light.srt
Normal file
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:05,325
|
||||
Your comparison of the Ukraine war to Turgenev's Fathers and Sons really hit home.
|
||||
|
||||
2
|
||||
00:00:05,325 --> 00:00:14,387
|
||||
You said Putin is the 'Father' fighting for Space (territory), while the youth in St. Petersburg are the 'Sons' who care about Time (the future).
|
||||
|
||||
3
|
||||
00:00:14,387 --> 00:00:19,200
|
||||
The 'Sons' are silent right now—'whispering on the Neva,' as you put it.
|
||||
|
||||
4
|
||||
00:00:19,200 --> 00:00:28,400
|
||||
My question is: In this tragic version of the story, do the Sons eventually inherit the house, or do the Fathers burn the house down before they die?
|
||||
|
||||
BIN
podcast_audios/project_multiguest/guest1_dmitri_callin.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest1_dmitri_callin.mp3
Normal file
Binary file not shown.
16
podcast_audios/project_multiguest/guest1_dmitri_callin.srt
Normal file
16
podcast_audios/project_multiguest/guest1_dmitri_callin.srt
Normal file
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:03,850
|
||||
Hello, this is Dmitri calling from Moscow.
|
||||
|
||||
2
|
||||
00:00:03,800 --> 00:00:09,712
|
||||
I found the paper's analysis of the Soviet Union's collapse particularly insightful.
|
||||
|
||||
3
|
||||
00:00:09,712 --> 00:00:18,725
|
||||
The author mentions how the Soviet Union's focus on military power at the expense of technological innovation led to its decline.
|
||||
|
||||
4
|
||||
00:00:18,725 --> 00:00:22,000
|
||||
Do you think this is still relevant today?
|
||||
|
||||
BIN
podcast_audios/project_multiguest/guest1_dmitri_callin_phone.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest1_dmitri_callin_phone.mp3
Normal file
Binary file not shown.
BIN
podcast_audios/project_multiguest/guest1_dmitri_conclusion.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest1_dmitri_conclusion.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:01,700
|
||||
Thank you.
|
||||
|
||||
2
|
||||
00:00:01,650 --> 00:00:08,562
|
||||
It's interesting to see how the paper connects these historical lessons to contemporary geopolitics.
|
||||
|
||||
3
|
||||
00:00:08,562 --> 00:00:17,275
|
||||
The rise of China as a technological power while maintaining a strong military presence shows that a balance is possible.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/guest2_priya_callin.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest2_priya_callin.mp3
Normal file
Binary file not shown.
16
podcast_audios/project_multiguest/guest2_priya_callin.srt
Normal file
16
podcast_audios/project_multiguest/guest2_priya_callin.srt
Normal file
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:03,325
|
||||
Hi, this is Priya from New Delhi.
|
||||
|
||||
2
|
||||
00:00:03,275 --> 00:00:09,512
|
||||
I was intrigued by the paper's section on '革命输出的会计困局' (the accounting dilemma of revolution export).
|
||||
|
||||
3
|
||||
00:00:09,512 --> 00:00:16,862
|
||||
The author argues that China's foreign aid policies during the Cold War suffered from conflicting objectives.
|
||||
|
||||
4
|
||||
00:00:16,862 --> 00:00:19,350
|
||||
Could you elaborate on this?
|
||||
|
||||
BIN
podcast_audios/project_multiguest/guest2_priya_callin_phone.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest2_priya_callin_phone.mp3
Normal file
Binary file not shown.
BIN
podcast_audios/project_multiguest/guest2_priya_conclusion.mp3
Normal file
BIN
podcast_audios/project_multiguest/guest2_priya_conclusion.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:01,862
|
||||
Fascinating.
|
||||
|
||||
2
|
||||
00:00:01,812 --> 00:00:10,600
|
||||
This perspective helps explain the evolution of China's foreign policy from the Cold War era to today's Belt and Road Initiative.
|
||||
|
||||
3
|
||||
00:00:10,600 --> 00:00:12,800
|
||||
Thank you for the insight.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host1_alex_final_thanks.mp3
Normal file
BIN
podcast_audios/project_multiguest/host1_alex_final_thanks.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:01,300
|
||||
Thank you, Priya.
|
||||
|
||||
2
|
||||
00:00:01,300 --> 00:00:04,412
|
||||
It's been great having both of you on the show today.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host1_alex_opening.mp3
Normal file
BIN
podcast_audios/project_multiguest/host1_alex_opening.mp3
Normal file
Binary file not shown.
8
podcast_audios/project_multiguest/host1_alex_opening.srt
Normal file
8
podcast_audios/project_multiguest/host1_alex_opening.srt
Normal file
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:02,675
|
||||
Welcome to Geopolitics Unpacked.
|
||||
|
||||
2
|
||||
00:00:02,675 --> 00:00:03,737
|
||||
I'm Alex.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host1_alex_question.mp3
Normal file
BIN
podcast_audios/project_multiguest/host1_alex_question.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:09,762
|
||||
Sarah, the paper introduces this fascinating concept of '轮庄博弈' (turn-based power game) to explain historical cycles.
|
||||
|
||||
2
|
||||
00:00:09,762 --> 00:00:14,125
|
||||
How does this apply to the rise and fall of the Warsaw Pact and NATO?
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:01,862
|
||||
Great question, Dmitri.
|
||||
|
||||
2
|
||||
00:00:01,862 --> 00:00:10,787
|
||||
The paper does highlight how the Soviet Union's decision to abandon the Setun ternary computer in favor of copying IBM's binary systems was a critical mistake.
|
||||
|
||||
3
|
||||
00:00:10,787 --> 00:00:17,412
|
||||
This technological stagnation, combined with the arms race,耗尽了 the Soviet economy.
|
||||
|
||||
4
|
||||
00:00:17,412 --> 00:00:18,862
|
||||
What do you think, Sarah?
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:01,762
|
||||
Thanks for calling, Priya.
|
||||
|
||||
2
|
||||
00:00:01,762 --> 00:00:05,687
|
||||
The paper uses an accounting metaphor to explain the problem.
|
||||
|
||||
3
|
||||
00:00:05,687 --> 00:00:19,087
|
||||
Traditional tributary systems had clear objectives (maintaining political order), but revolutionary export tried to achieve both political returns and selfless aid simultaneously, leading to confusion and inefficiency.
|
||||
|
||||
4
|
||||
00:00:19,087 --> 00:00:21,262
|
||||
Sarah, could you expand on this?
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host2_sarah_final.mp3
Normal file
BIN
podcast_audios/project_multiguest/host2_sarah_final.mp3
Normal file
Binary file not shown.
8
podcast_audios/project_multiguest/host2_sarah_final.srt
Normal file
8
podcast_audios/project_multiguest/host2_sarah_final.srt
Normal file
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:08,987
|
||||
Join us next time as we continue exploring the insights from Ben Xu's 'A Tale of 2 Treaties' and their relevance to contemporary geopolitics.
|
||||
|
||||
2
|
||||
00:00:08,937 --> 00:00:13,350
|
||||
Until then, this is Geopolitics Unpacked signing off.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host2_sarah_opening.mp3
Normal file
BIN
podcast_audios/project_multiguest/host2_sarah_opening.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:01,937
|
||||
And I'm Sarah.
|
||||
|
||||
2
|
||||
00:00:01,887 --> 00:00:09,587
|
||||
Today we're discussing Ben Xu's paper 'A Tale of 2 Treaties' and exploring the geopolitical dynamics of the Cold War era.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host2_sarah_response.mp3
Normal file
BIN
podcast_audios/project_multiguest/host2_sarah_response.mp3
Normal file
Binary file not shown.
12
podcast_audios/project_multiguest/host2_sarah_response.srt
Normal file
12
podcast_audios/project_multiguest/host2_sarah_response.srt
Normal file
@@ -0,0 +1,12 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:01,850
|
||||
It's brilliant.
|
||||
|
||||
2
|
||||
00:00:01,800 --> 00:00:11,737
|
||||
The paper argues that just like in a mahjong game, the '庄家' (庄家) tries to maintain power by exploiting the '闲家' (闲家), but eventually gets overthrown by a coalition of the exploited.
|
||||
|
||||
3
|
||||
00:00:11,737 --> 00:00:21,237
|
||||
Applied to the Cold War, this explains how the Soviet Union's attempts to maintain control over its satellite states led to the collapse of the Warsaw Pact.
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:02,562
|
||||
Absolutely, Dmitri.
|
||||
|
||||
2
|
||||
00:00:02,512 --> 00:00:09,000
|
||||
The paper's analysis of the '赛博共产主义' (cyber communism) vision that never materialized is fascinating.
|
||||
|
||||
3
|
||||
00:00:09,000 --> 00:00:19,437
|
||||
The Soviet Union had the technical expertise to develop advanced computing systems, but bureaucratic interests and a focus on military might derailed those efforts.
|
||||
|
||||
4
|
||||
00:00:19,437 --> 00:00:26,500
|
||||
This is a cautionary tale for any nation that prioritizes military power over technological innovation.
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:02,275
|
||||
Definitely, Priya.
|
||||
|
||||
2
|
||||
00:00:02,225 --> 00:00:12,600
|
||||
The paper argues that this accounting dilemma led to situations where China provided significant aid to countries like Albania and Vietnam without clear strategic returns.
|
||||
|
||||
3
|
||||
00:00:12,600 --> 00:00:17,350
|
||||
When these relationships soured, it created diplomatic challenges.
|
||||
|
||||
4
|
||||
00:00:17,350 --> 00:00:27,937
|
||||
The author suggests that this experience influenced China's more pragmatic foreign aid policies today, which are more focused on mutual benefit through economic cooperation.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/host2_sarah_thanks_dmitri.mp3
Normal file
BIN
podcast_audios/project_multiguest/host2_sarah_thanks_dmitri.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:02,812
|
||||
That's a great point, Dmitri.
|
||||
|
||||
2
|
||||
00:00:02,762 --> 00:00:04,837
|
||||
Thank you for calling in.
|
||||
|
||||
BIN
podcast_audios/project_multiguest/multi_guest_callin_podcast.mp3
Normal file
BIN
podcast_audios/project_multiguest/multi_guest_callin_podcast.mp3
Normal file
Binary file not shown.
180
podcast_audios/project_multiguest/multi_guest_callin_podcast.srt
Normal file
180
podcast_audios/project_multiguest/multi_guest_callin_podcast.srt
Normal file
@@ -0,0 +1,180 @@
|
||||
1
|
||||
00:00:00,050 --> 00:00:02,675
|
||||
Welcome to Geopolitics Unpacked.
|
||||
|
||||
2
|
||||
00:00:02,675 --> 00:00:03,737
|
||||
I'm Alex.
|
||||
|
||||
3
|
||||
00:00:03,892 --> 00:00:05,729
|
||||
And I'm Sarah.
|
||||
|
||||
4
|
||||
00:00:05,679 --> 00:00:13,379
|
||||
Today we're discussing Ben Xu's paper 'A Tale of 2 Treaties' and exploring the geopolitical dynamics of the Cold War era.
|
||||
|
||||
5
|
||||
00:00:13,490 --> 00:00:23,202
|
||||
Sarah, the paper introduces this fascinating concept of '轮庄博弈' (turn-based power game) to explain historical cycles.
|
||||
|
||||
6
|
||||
00:00:23,202 --> 00:00:27,565
|
||||
How does this apply to the rise and fall of the Warsaw Pact and NATO?
|
||||
|
||||
7
|
||||
00:00:27,724 --> 00:00:29,474
|
||||
It's brilliant.
|
||||
|
||||
8
|
||||
00:00:29,424 --> 00:00:39,361
|
||||
The paper argues that just like in a mahjong game, the '庄家' (庄家) tries to maintain power by exploiting the '闲家' (闲家), but eventually gets overthrown by a coalition of the exploited.
|
||||
|
||||
9
|
||||
00:00:39,361 --> 00:00:48,861
|
||||
Applied to the Cold War, this explains how the Soviet Union's attempts to maintain control over its satellite states led to the collapse of the Warsaw Pact.
|
||||
|
||||
10
|
||||
00:00:49,012 --> 00:00:52,762
|
||||
Hello, this is Dmitri calling from Moscow.
|
||||
|
||||
11
|
||||
00:00:52,712 --> 00:00:58,624
|
||||
I found the paper's analysis of the Soviet Union's collapse particularly insightful.
|
||||
|
||||
12
|
||||
00:00:58,624 --> 00:01:07,637
|
||||
The author mentions how the Soviet Union's focus on military power at the expense of technological innovation led to its decline.
|
||||
|
||||
13
|
||||
00:01:07,637 --> 00:01:10,912
|
||||
Do you think this is still relevant today?
|
||||
|
||||
14
|
||||
00:01:13,518 --> 00:01:15,330
|
||||
Great question, Dmitri.
|
||||
|
||||
15
|
||||
00:01:15,330 --> 00:01:24,255
|
||||
The paper does highlight how the Soviet Union's decision to abandon the Setun ternary computer in favor of copying IBM's binary systems was a critical mistake.
|
||||
|
||||
16
|
||||
00:01:24,255 --> 00:01:30,880
|
||||
This technological stagnation, combined with the arms race,耗尽了 the Soviet economy.
|
||||
|
||||
17
|
||||
00:01:30,880 --> 00:01:32,330
|
||||
What do you think, Sarah?
|
||||
|
||||
18
|
||||
00:01:32,480 --> 00:01:34,942
|
||||
Absolutely, Dmitri.
|
||||
|
||||
19
|
||||
00:01:34,892 --> 00:01:41,380
|
||||
The paper's analysis of the '赛博共产主义' (cyber communism) vision that never materialized is fascinating.
|
||||
|
||||
20
|
||||
00:01:41,380 --> 00:01:51,817
|
||||
The Soviet Union had the technical expertise to develop advanced computing systems, but bureaucratic interests and a focus on military might derailed those efforts.
|
||||
|
||||
21
|
||||
00:01:51,817 --> 00:01:58,880
|
||||
This is a cautionary tale for any nation that prioritizes military power over technological innovation.
|
||||
|
||||
22
|
||||
00:01:59,048 --> 00:02:00,648
|
||||
Thank you.
|
||||
|
||||
23
|
||||
00:02:00,598 --> 00:02:07,510
|
||||
It's interesting to see how the paper connects these historical lessons to contemporary geopolitics.
|
||||
|
||||
24
|
||||
00:02:07,510 --> 00:02:16,223
|
||||
The rise of China as a technological power while maintaining a strong military presence shows that a balance is possible.
|
||||
|
||||
25
|
||||
00:02:16,376 --> 00:02:19,088
|
||||
That's a great point, Dmitri.
|
||||
|
||||
26
|
||||
00:02:19,038 --> 00:02:21,113
|
||||
Thank you for calling in.
|
||||
|
||||
27
|
||||
00:02:21,272 --> 00:02:24,497
|
||||
Hi, this is Priya from New Delhi.
|
||||
|
||||
28
|
||||
00:02:24,447 --> 00:02:30,684
|
||||
I was intrigued by the paper's section on '革命输出的会计困局' (the accounting dilemma of revolution export).
|
||||
|
||||
29
|
||||
00:02:30,684 --> 00:02:38,034
|
||||
The author argues that China's foreign aid policies during the Cold War suffered from conflicting objectives.
|
||||
|
||||
30
|
||||
00:02:38,034 --> 00:02:40,522
|
||||
Could you elaborate on this?
|
||||
|
||||
31
|
||||
00:02:43,138 --> 00:02:44,850
|
||||
Thanks for calling, Priya.
|
||||
|
||||
32
|
||||
00:02:44,850 --> 00:02:48,775
|
||||
The paper uses an accounting metaphor to explain the problem.
|
||||
|
||||
33
|
||||
00:02:48,775 --> 00:03:02,175
|
||||
Traditional tributary systems had clear objectives (maintaining political order), but revolutionary export tried to achieve both political returns and selfless aid simultaneously, leading to confusion and inefficiency.
|
||||
|
||||
34
|
||||
00:03:02,175 --> 00:03:04,350
|
||||
Sarah, could you expand on this?
|
||||
|
||||
35
|
||||
00:03:04,500 --> 00:03:06,675
|
||||
Definitely, Priya.
|
||||
|
||||
36
|
||||
00:03:06,625 --> 00:03:17,000
|
||||
The paper argues that this accounting dilemma led to situations where China provided significant aid to countries like Albania and Vietnam without clear strategic returns.
|
||||
|
||||
37
|
||||
00:03:17,000 --> 00:03:21,750
|
||||
When these relationships soured, it created diplomatic challenges.
|
||||
|
||||
38
|
||||
00:03:21,750 --> 00:03:32,337
|
||||
The author suggests that this experience influenced China's more pragmatic foreign aid policies today, which are more focused on mutual benefit through economic cooperation.
|
||||
|
||||
39
|
||||
00:03:32,508 --> 00:03:34,270
|
||||
Fascinating.
|
||||
|
||||
40
|
||||
00:03:34,220 --> 00:03:43,008
|
||||
This perspective helps explain the evolution of China's foreign policy from the Cold War era to today's Belt and Road Initiative.
|
||||
|
||||
41
|
||||
00:03:43,008 --> 00:03:45,208
|
||||
Thank you for the insight.
|
||||
|
||||
42
|
||||
00:03:45,322 --> 00:03:46,572
|
||||
Thank you, Priya.
|
||||
|
||||
43
|
||||
00:03:46,572 --> 00:03:49,684
|
||||
It's been great having both of you on the show today.
|
||||
|
||||
44
|
||||
00:03:49,788 --> 00:03:58,675
|
||||
Join us next time as we continue exploring the insights from Ben Xu's 'A Tale of 2 Treaties' and their relevance to contemporary geopolitics.
|
||||
|
||||
45
|
||||
00:03:58,625 --> 00:04:03,038
|
||||
Until then, this is Geopolitics Unpacked signing off.
|
||||
|
||||
BIN
podcast_audios/project_priya/indian_priya.mp3
Normal file
BIN
podcast_audios/project_priya/indian_priya.mp3
Normal file
Binary file not shown.
20
podcast_audios/project_priya/indian_priya.srt
Normal file
20
podcast_audios/project_priya/indian_priya.srt
Normal file
@@ -0,0 +1,20 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:02,937
|
||||
You were extremely harsh on India.
|
||||
|
||||
2
|
||||
00:00:02,887 --> 00:00:14,525
|
||||
You said it's a country named after a river (the Indus) that it doesn't even own, and that it's essentially a 'franchise operation' left over from the East India Company.
|
||||
|
||||
3
|
||||
00:00:14,525 --> 00:00:23,637
|
||||
You argued that because they never had a 'Land Revolution' (shuffling the Mahjong deck), they are stuck in a deadlock of caste and inefficiency.
|
||||
|
||||
4
|
||||
00:00:23,637 --> 00:00:28,450
|
||||
But look at all the Indian CEOs running Silicon Valley today.
|
||||
|
||||
5
|
||||
00:00:28,450 --> 00:00:36,200
|
||||
Doesn't that prove the 'software' of the people is fine, and you're underestimating their potential to fix the 'hardware'?
|
||||
|
||||
BIN
podcast_audios/project_priya/indian_priya_intense.mp3
Normal file
BIN
podcast_audios/project_priya/indian_priya_intense.mp3
Normal file
Binary file not shown.
20
podcast_audios/project_priya/indian_priya_intense.srt
Normal file
20
podcast_audios/project_priya/indian_priya_intense.srt
Normal file
@@ -0,0 +1,20 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:02,937
|
||||
You were extremely harsh on India.
|
||||
|
||||
2
|
||||
00:00:02,887 --> 00:00:14,525
|
||||
You said it's a country named after a river (the Indus) that it doesn't even own, and that it's essentially a 'franchise operation' left over from the East India Company.
|
||||
|
||||
3
|
||||
00:00:14,525 --> 00:00:23,637
|
||||
You argued that because they never had a 'Land Revolution' (shuffling the Mahjong deck), they are stuck in a deadlock of caste and inefficiency.
|
||||
|
||||
4
|
||||
00:00:23,637 --> 00:00:28,450
|
||||
But look at all the Indian CEOs running Silicon Valley today.
|
||||
|
||||
5
|
||||
00:00:28,450 --> 00:00:36,200
|
||||
Doesn't that prove the 'software' of the people is fine, and you're underestimating their potential to fix the 'hardware'?
|
||||
|
||||
BIN
podcast_audios/project_sophie/british_sophie.mp3
Normal file
BIN
podcast_audios/project_sophie/british_sophie.mp3
Normal file
Binary file not shown.
20
podcast_audios/project_sophie/british_sophie.srt
Normal file
20
podcast_audios/project_sophie/british_sophie.srt
Normal file
@@ -0,0 +1,20 @@
|
||||
1
|
||||
00:00:00,100 --> 00:00:03,112
|
||||
Your section on Japan was eye-opening.
|
||||
|
||||
2
|
||||
00:00:03,062 --> 00:00:13,225
|
||||
You said Japan's entire post-WW2 identity is built on a lie: that they were the 'victims of American nuclear aggression' when they were actually the aggressors who got lucky.
|
||||
|
||||
3
|
||||
00:00:13,225 --> 00:00:18,637
|
||||
You compared them to the 'cool kid in school who pretends to be humble but is secretly arrogant.
|
||||
|
||||
4
|
||||
00:00:18,637 --> 00:00:24,700
|
||||
But Japan has apologized many times, and they've been a peaceful nation for 75 years.
|
||||
|
||||
5
|
||||
00:00:24,700 --> 00:00:28,562
|
||||
Is this just another case of 'history is written by the losers'?
|
||||
|
||||
Reference in New Issue
Block a user