banner
Nix

Nix

正在作为一个废物|开心的生活|学习产生快乐的事物
twitter
bilibili

我的雙語字幕工作流

寫在前面#

Final Cut Pro 的原生字幕並不好用,在製作批量字幕時,會導致繁重的工作量。比如當我擁有逐字稿時,從 Pages 到 FCP 之間,不停地 ⌘ + C ⌘ + V 引起了我的極大痛苦,還包括為了選中對象不得不在觸控板上指尖飛舞。

轉折,總是發生在壞的時刻。這也就是如下工作流的由來。

逐字稿#

是的。這套工作流的適用場景,在於你首先有一份逐字稿。通常是以下場景:

  • 客戶提供的已校對文案
  • 歌詞字幕
  • 影視劇台詞

製作字幕的逐字稿可以保存為 TXT 純文本。

This is 1st subtitle.
這是第 1 條字幕
This is 2nd subtitle.
這是第 2 條字幕

不要有空行,因為懶得寫空行處理…(你當然可以自行添加

字幕時間軸#

一般來說,製作時間軸可以有兩種方式:手動打軸和自動(AI)打軸。

手動打軸#

主要依靠聽力和音頻波形,例如在 ArcTime 這樣的字幕製作軟件上進行手動打軸 (拖拽或 JK 鍵拍打)。當然,ArcTime 對於雙語字幕的支持十分友好,可以參看官方使用教程:雙語字幕的製作流程

Arctime 雙語字幕的製作流程

自動打軸#

字節跳動旗下的視頻剪輯軟件 剪映 被諸多視頻 up 主稱為最好用的「字幕製作」工具。因其 免費 的語音轉文字功能(智能字幕),而且準確率也還不錯,於是過去常用的 網易見外 也就被我喜新厭舊了…

剪映的軟件界面,字幕功能有識別字幕和文稿匹配,以及導入本地字幕

目前自動打軸的體驗,對於語句起、終點的判斷還不錯,但在斷句上還存在一些不足。這裡的不足,主要是針對逐字稿而言的。它不能很好地與逐字稿的分行進行匹配。這也正是我對於「文稿匹配」的全部幻想。也許再過幾個版本,剪映就可以實現真正的文稿匹配吧!

只是當下,還需要多一步人工校軸。把錯誤的斷行對應逐字稿合併 / 分割。但這部分的工作量相對於手動打軸已經輕鬆很多了。此處也是全流程的決速步!希望有更好的優化方案。

時間軸可以選擇導出為 SRT 文件。

1
00:02:14,000 --> 00:03:14,000
This is 1st subtitle.

2
00:05:21,000 --> 00:13:14,000
This is 2nd subtitle.

替換字幕文本#

校軸完畢後,就可以導出 SRT 字幕文件了。在這裡,也許你會基於剪映生成的字幕文本做修改。對於雙語字幕,會再複製一層字幕軌道,進行 ⌘ + C ⌘ + V 的逐個替換。

但仔細想想,既然它們都是結構化的文本,那自然可以通過程序來批量化處理。

例如以下的 Python 代碼(ChatGPT 可以幫你清晰地註釋每一處的功能呢~

# txt_to_srt.py

import pysrt

# 定義輸入文件路徑
srt_file_path = 'path/to/your/srt/file.srt'
txt_file_path = 'path/to/your/txt/file.txt'

# 定義輸出文件路徑
new_srt_file_EN_path = 'path/to/your/srt/file_EN.srt'
new_srt_file_ZH_path = 'path/to/your/srt/file_ZH.srt'

# 讀取 txt 文件中的文本
with open(txt_file_path, 'r', encoding='utf-8') as txt_file:
    replacement_content = txt_file.read()

# 將 txt 文件分割為句子列表
replacement_text = replacement_content.split('\n')

# 初始化中英文列表
english_sentences = []
chinese_sentences = []

# 分別提取中英文句子
for i in range(len(replacement_text)):
    if i % 2 == 0:  # 偶數行為英文句子(注:從 0 行開始計數)
        english_sentences.append(replacement_text[i])  # 添加到英文列表
    else:  # 奇數行為中文句子
        chinese_sentences.append(replacement_text[i])  # 添加到中文列表

# 使用 pysrt 庫加載 SRT 文件
subs_EN = pysrt.open(srt_file_path)
subs_ZH = pysrt.open(srt_file_path)

# 遍歷每個字幕條目,將文本替換為 txt 文件中的文本
for id, sub in enumerate(subs_EN):
    sub.text = english_sentences[id]

for id, sub in enumerate(subs_ZH):
    sub.text = chinese_sentences[id]

# 將修改後的字幕保存到新的 SRT 文件中
subs_EN.save(new_srt_file_EN_path, encoding='utf-8')
subs_ZH.save(new_srt_file_ZH_path, encoding='utf-8') 

print("字幕替換完成!")

"""
請確保已經安裝了 pysrt 庫,您可以使用 pip 命令來安裝它:pip install pysrt。
同時,請將 srt_file_path、txt_file_path 和 new_srt_file_EN_path、new_srt_file_ZH_path 替換為您實際的文件路徑。
這段代碼會將 SRT 文件中的所有字幕文本替換為 txt 文件中的文本,並將修改後的字幕保存到新的 SRT 文件中。
"""

輸入

txt file
---
This is 1st subtitle.
這是第 1 條字幕
This is 2nd subtitle.
這是第 2 條字幕
srt file
---
1
00:02:14,000 --> 00:03:14,000
left blank intentionally.

2
00:05:21,000 --> 00:13:14,000
left blank intentionally.

運行

python txt_to_srt.py

輸出

srt file EN
---
1
00:02:14,000 --> 00:03:14,000
This is 1st subtitle.

2
00:05:21,000 --> 00:13:14,000
This is 2nd subtitle.
srt file ZH
---
1
00:02:14,000 --> 00:03:14,000
這是第 1 條字幕

2
00:05:21,000 --> 00:13:14,000
這是第 2 條字幕

導入至剪輯軟件#

剪映:支持導入 SRT 字幕。導入後,編輯樣式,導出視頻,交付。

Final Cut Pro:由於我當前主要使用 Final Cut Pro,所以需要通過 XML 來導入字幕。也因此產生了 SRT 文件轉換為 FCPXML 文件 的需求。

FCPXML 模版文件 Template.fcpxml
---

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fcpxml>

<fcpxml version="1.10">
    <resources>
        <format id="r1" name="FFVideoFormat1080p2997" frameDuration="1001/30000s" width="1920" height="1080" colorSpace="1-1-1 (Rec. 709)"/>
        <effect id="r2" name="基本字幕" uid=".../Titles.localized/Bumper:Opener.localized/Basic Title.localized/Basic Title.moti"/>
    </resources>
    <library>
        <event name="{EVENT_NAME}">
            <project name="{PROJECT_NAME}">
                <sequence format="r1" tcStart="0s" tcFormat="NDF">
                    <spine>
                        <title ref="r2" name="{TITLE_NO}" offset="{OFFSET}" duration="{DURATION}" start="{START}">
                            <param name="展平" key="9999/999166631/999166633/2/351" value="1"/>
                            <param name="對齊" key="9999/999166631/999166633/2/354/999169573/401" value="1 (居中)"/>
                            <text>
                                <text-style ref="ts1">{TEXT}</text-style>
                            </text>
                            <text-style-def id="ts1">
                                <text-style font="Noto Sans SC" fontSize="42" fontFace="Regular" fontColor="1 1 1 1" shadowColor="0 0 0 0.75" shadowOffset="5 315" shadowBlurRadius="4"/>
                            </text-style-def>
                            <adjust-transform position="0 -40.7407"/>
                        </title>
                    </spine>
                </sequence>
            </project>
        </event>
    </library>
</fcpxml>

在線轉換#

crossub 字幕轉換工具

本地轉換#

我在 GitHub 上找到了這個項目 hysmichael/srt_fcpxml_converter。該作者實現了 SRT 與 FCPXML 之間的雙向轉換。

輸入

srt file EN
---
1
00:02:14,000 --> 00:03:14,000
This is 1st subtitle.

2
00:05:21,000 --> 00:13:14,000
This is 2nd subtitle.

配合 FCPXML 模版文件 Template.fcpxml。該模版文件也可以自行在 Final Cut Pro 中調整樣式,導出為 FCPXML 文件作為模版。

運行

python srt_converter.py -i INPUT_FILE.srt -o OUTPUT_FILE.fcpxml

輸出並導入 Final Cut Pro
從 SRT 轉換為 FCPXML 文件,並導入 Final Cut Pro

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。