
一則公開的研究問題,問怎樣為一項研究收集 TikTok 字幕文字。它也問怎樣檢查準確度,以及怎樣在 R 裡分析文字。R 是用來處理表格和次數的程式。這條問題顯示有這個需要。它沒有證明這個方法有效。它也沒有顯示有多少研究需要它。見關於 TikTok 字幕文字的公開問題。
你用 Actor 收集資料行。Actor 是託管的資料收集程式。託管是指它以服務形式運行,不是你電腦上的一個檔案。這個 Actor 是 TikTok Transcript Scraper。Task 是已儲存的輸入預設。預設是一套已儲存的輸入選擇。目前的 Task 是 TikTok Transcript Dataset for Content Analysis。Actor 收集來源資料行。編碼和計數由你來做。公開的 Task 只是起始輸入。它不代表分析會自己運行。
目前的收集程式回傳甚麼
這些公開事實在 2026-10-13 已核對。目前版本是 0.1.36。每次執行在 `startUrls` 接受 1 至 100 個已知的公開目標。目標可以是影片 URL、短連結,或數字影片 ID。這個 Actor 不會搜尋個人檔案、關鍵字或聲音頁。你必須已經知道那些影片。
`preferredLanguages` 是一份按次序排列的公開字幕語言清單。Actor 選第一條相符的公開字幕軌。空白清單會用第一條公開字幕軌。它不會翻譯文字。沒有字幕的聲音,它不會從聲音產生文字。它不收集留言。它不指派內容編碼。
已儲存的 Task 輸入是:
{"startUrls": ["https://www.tiktok.com/@hankgreen1/video/7047596209028074758"], "preferredLanguages": []}用你自己已知的公開影片,取代那個樣本。若只試一條影片,在 `startUrls` 放一個 URL。若研究語言是英文,把 `preferredLanguages` 設為 `["en"]`。若研究用另一種語言,寫下該語言規則,並用它的語言代碼。不要把 `["en"]` 抄進另一種語言的研究。空白清單可能回傳某一條其他公開字幕軌。
資料集的每一行對應一個已提交的輸入。失敗的輸入仍會有一行。保留該行。它是這次嘗試的證據。這些欄位名稱必須完全一致:`inputIndex`、`inputUrl`、`videoId`、`videoUrl`、`authorHandle`、`durationSeconds`、`languageCode`、`text`、`segments`、`status`、`statusReason`、`isBillable` 和 `scrapedAt`。每個片段有 `startSeconds`、`endSeconds` 和 `text`。TikTok 的時間用這兩個鍵。`startSeconds` 和 `endSeconds` 照回傳值使用。每個 `videoId` 都當文字保留,不要當數字。若程式把很長的 ID 存成數字,這個 ID 可能會改變。
`status` 可以是 `succeeded`、`no_public_captions`、`language_unavailable`、`duplicate_input`、`not_tiktok`、`invalid_input`、`unsupported_url`、`video_unavailable`、`not_public` 或 `blocked_or_challenged`。擷取失敗和字幕失敗也可能出現。成功必須有非空白的文字。失敗狀態配上空值或空白字幕,並不是說話中的沉默。影片仍可能有說話。你只知道沒有可用的字幕回來。
只有成功的原生字幕結果,`isBillable` 才是 true。這個欄位名稱用小寫的 b。其他行仍留在資料裡,作為證據。`isBillable` 不是描述整次執行。一次執行可以同時有 true 和 false 的行。不要把整次執行說成免費。
這次執行的帳目使用這些準確名稱:`inputsReceived`、`resultRows`、`billableTranscriptRows`、`nonBillableResultRows`、`duplicateVideosSkipped` 和 `statusCounts`。這份帳目用來核對這次執行。它不表示你的影片代表所有創作者。
2026-10-13 的一次單片核對,用了已儲存的樣本。該行成功。影片 ID 是所要求的 ID,`7047596209028074758`。語言代碼是 `eng-US`。像 `eng-US` 這樣的代碼是地區字幕標籤。它表示英文,並帶有美國地區標籤。它不是翻譯。文字不是空白。該行有 12 個片段。片段時間資料包含 `startSeconds` 和 `endSeconds` 這兩個鍵。這裡不重複該影片的字幕字詞。這次核對只證明那一個來源有公開字幕路徑。它不證明字詞完全正確。它不證明每一條影片都會成功。它不證明你的內容編碼有效。你仍須做自己的試行。
八個步驟
- 界定問題、編碼和樣本
寫一條研究問題。寫一條你可以數算的內容編碼。內容編碼是你標為出現或不出現的特徵。按一條你能說清楚的規則,選擇已知的影片 URL。收集之前,先說明時段、語言和創作者範圍。
抽樣清單是你選中的每一條影片的名單。先填好這份清單,再看字幕。不要只因為有字幕就選影片。若你只保留有字幕的影片,樣本就已經改變。沒有字幕的影片會消失,而不是顯示為缺失。
- 先聲明計算單位
選擇你要數算的單位。單位可以是一條影片、一個字幕片段,或你界定的一段文字。在這些步驟裡,被數算的單位是影片。片段是一段有時間的字幕文字。片段是該影片的證據。它們不是額外的影片。
三個片段有同一個編碼,仍只算一條影片。執行之前先寫下這條規則。保留輸入 URL、回傳的 `videoId`,以及你自己的 `selected_video_key`。研究鍵是你的。即使 URL 形式改變,它仍保持不變。
- 先測試一條已選影片
任何批次之前,先執行一條已選影片。這是試行。試行是對整條路徑的小型測試。檢查 `status`、`videoId`、`languageCode` 和 `text`。成功時文字必須非空白。若研究語言是英文,在這次試行把 `preferredLanguages` 設為 `["en"]`。
然後把一段短文字和聲音比較。也看畫面上的影像。寫下漏掉的字、多出的字和錯誤的字。成功的一行不證明字詞準確。上面的 12 個片段核對,只顯示公開路徑可以回傳字幕。那不是你的核對。
- 執行有上限的清單,再對帳
只送出你已知的 URL,一次執行最多 100 個。更長的已選清單需要另一次執行。把每個已提交的輸入對到一行結果。用 `inputIndex`、`inputUrl` 和 `videoId`。再把那些行對到這次執行的帳目。
檢查 `inputsReceived`、`resultRows`、`billableTranscriptRows`、`nonBillableResultRows`、`duplicateVideosSkipped` 和 `statusCounts`。重複項記在備註裡,該影片只算一次。缺失的字幕留在清單裡,但放在成功集合之外。來源存取失敗也一樣處理。那些狀態包括 `video_unavailable`、`not_public`、`blocked_or_challenged`、`unsupported_url`、`not_tiktok` 和 `invalid_input`。
決不要把失敗的空白文字編碼成「編碼不存在」。空白文字表示你沒有觀察到該編碼。它不表示該編碼不存在。
- 做影片表和片段表
每條已選影片做一行。用這些欄:`selected_video_key`、`videoId`、`videoUrl`、`languageCode`、`caption_status`、`caption_validated`、`study_eligible` 和 `exclusion_reason`。`study_eligible` 記錄該影片可否納入計數。它不是內容編碼。`caption_validated` 記錄你有沒有把字幕和影片核對。
未能核對字幕時,用 `unknown`。真實狀態是未知時,不要把 `caption_validated` 寫成 no。失敗的一行沒有被核對。未完成的覆核也沒有被核對。
片段放在第二張表。用影片鍵、`startSeconds`、`endSeconds`、`text`,以及一項來源觀察。把片段陣列放在試算表的一個儲存格裡,是很差的匯出。CSV 是平面文字表,資料按行和欄排列。嵌套的片段清單不能安全地直接放進這種表格結構。先匯出 JSON。JSON 是一種文字格式,可以在一個項目裡保留清單。然後另行把片段清單攤平。攤平是指每個片段做成單獨的一行。在每個片段的那一行重複影片鍵。不要按逗號拆開文字。句子裡有逗號。原始字幕文字保持不變。每個編碼都放在新欄。
- 寫一條小編碼規則,並在虛構例子上試用
從這一步起的例子都是虛構。它們不是 Actor 的輸出。不要把這些 ID 貼進真實輸入。它們的影片 URL 是未知的。
寫一條短規則,並給它一個版本。若是簡單的全字相符規則,要界定該字、字母大小寫,以及字詞邊界。字詞邊界避免一個短字在較長的字裡面相符。含糊用法由你自己覆核。關鍵字規則只找出該模式。它不證明說話的人想表達甚麼。只靠畫面傳達的訊息,可以和字幕文字不一致。諷刺也可以和文字不一致。這些情況需要人來編碼。
這裡的虛構編碼,是量度水的明確指示。規則版本 v1:已核對的字幕文字給出該指示時,標為編碼 1。整個字 "measure" 在任何字母大小寫都計算。字 "measurement" 是另一個字。要覆核它。不要只靠關鍵字規則標它。只有已核對、而且沒有該指示的字幕,才可以標編碼 0。否則編碼保持未知。
- 先核對一小組試行資料,再匯入 R
大型研究之前,先為一小組試行資料編碼。兩個人可以分開編碼。或者你稍後再編一次,然後比較。儲存 `code`、`code_version`、`coder`、`decision_note` 和一個時間戳。時間戳記錄決定是何時作出的。原始文字放在自己的欄。
R 可以讀取平面 CSV。告訴 R,ID 欄是文字。不要讓 R 把 ID 猜成數字。下面的片段只用 base R。它用虛構的行。它不加入套件。它不是經過測試的研究標準。這裡 `denom` 是分母。分母是你用來相除的合資格影片數目。`NA` 表示不可用。這個例子用 `NA` 表示未知編碼。
videos <- data.frame(
videoId = c("video-v1", "video-v2", "video-v3", "video-v4", "video-v5"),
study_eligible = c("yes", "yes", "no", "no", "no"),
code = c(1, 0, NA, NA, NA),
stringsAsFactors = FALSE
)
stopifnot(is.character(videos[["videoId"]]))
eligible <- videos[["study_eligible"]] == "yes"
stopifnot(!any(is.na(videos[["code"]][eligible])))
code_count <- sum(videos[["code"]][eligible])
denom <- sum(eligible)
share <- code_count / denom`code_count` 是 1。`denom` 是 2。`share` 是 0.5。`NA` 值是未知編碼。它們不是零。`stopifnot` 那一行會在合資格影片有未知編碼時停止這個指令碼。
匯出真實 CSV 時,保留同一個文字檢查:
videos_from_csv <- read.csv(
"video_table.csv",
stringsAsFactors = FALSE,
colClasses = c(videoId = "character")
)
stopifnot(is.character(videos_from_csv[["videoId"]]))你也可以在 base R 測試這條虛構的字詞規則:
raw_text <- "I measure the water before I pour it"
hit <- grepl("\\bmeasure\\b", raw_text, ignore.case = TRUE)
ambiguous <- grepl("\\bmeasure\\b", "measurement", ignore.case = TRUE)`hit` 是 TRUE。`ambiguous` 是 FALSE。第二個結果說明:較長的字需要人工覆核規則,不能未經覆核就視為相符。
- 連同完整結果清單一起報告次數
編碼占比的分母,只用合資格影片。合資格是指 `succeeded`、文字非空白,以及 `caption_validated` 為 yes。在該占比旁邊,報告每條已選影片的結果。讀者必須看到失敗和未完成的行。把發現限制在你選中並觀察到的影片。不要把它說成所有創作者的結果。不要把它說成所有政治言論的結果。
缺失的字幕可以改變結論。本文停在這份清單。它不教那些缺失的行可以令結果改變多少。
虛構的五條影片計數
同一個虛構例子在這裡繼續。V1 至 V5 是編造的研究標籤。`videoId` 的值是編造的文字標籤。它們不是真實的 TikTok ID。每一行的 `videoUrl` 都是未知。不要把這些標籤送給 Actor。真實的 `languageCode` 可以是地區值,例如 `eng-US`。這個虛構例子用 `en`,因為聲明的研究語言是英文。在表裡,unknown 是研究用的值。在 R 例子裡,`NA` 儲存同一個未知。不要把未知存成 0。
所聲明的編碼仍是量度水的明確指示。
V1 是英文。它成功。字幕已核對。文字是 "I measure the water before I pour it"。這段文字是量度水的明確指示。編碼是 1。
V2 是英文。它成功。字幕已核對。文字是 "I pour water into the tray"。它叫人倒水。它沒有叫人量度。編碼是 0。
V3 的狀態是 `no_public_captions`。文字是空白。`languageCode` 是未知。不要編造一個。`caption_validated` 是 unknown,不是 no。編碼是未知。空白文字不是編碼 0。它也不是沉默的證明。
V4 的狀態是 `language_unavailable`。文字是空白。`languageCode` 是未知。`caption_validated` 是 unknown。編碼是未知。這個失敗和 V3 的失敗不同。把兩個原因分開保留。
V5 是英文。它成功。有人把字幕和聲音比較。字幕漏了量度語句。核對未完成。`caption_validated` 是 unknown,不是 no。`study_eligible` 是 no。編碼保持未知。成功不等於可信的字幕。不要把這一行變成編碼 0。
只有 `study_eligible` 是 yes 時,影片才進入占比。這個決定和編碼分開。V1 和 V2 合資格,因為字幕成功、文字非空白,而且有人核對過。V3 和 V4 不合資格,因為收集失敗。V5 不合資格,因為核對未完成。V1、V2 和 V5 的 `isBillable` 會是 true,因為那些字幕結果成功。V3 和 V4 的 `isBillable` 會是 false。V5 可計費,但仍不合資格。可計費標記不決定研究中計算的影片數目。
影片表:
| selected_video_key | videoId | videoUrl | languageCode | caption_status | caption_validated | study_eligible | exclusion_reason |
|---|---|---|---|---|---|---|---|
| V1 | video-v1 | unknown | en | succeeded | yes | yes | none |
| V2 | video-v2 | unknown | en | succeeded | yes | yes | none |
| V3 | video-v3 | unknown | unknown | no_public_captions | unknown | no | 沒有公開字幕;空白文字未編碼 |
| V4 | video-v4 | unknown | unknown | language_unavailable | unknown | no | 所要求的語言缺失;空白文字未編碼 |
| V5 | video-v5 | unknown | en | succeeded | unknown | no | 聲音覆核未完成;漏了量度語句 |
編碼表:
| selected_video_key | code | code_version | coder | decision_note | timestamp |
|---|---|---|---|---|---|
| V1 | 1 | v1 | coder-a | 量度水的明確指示 | example-only |
| V2 | 0 | v1 | coder-a | 只有倒水的指示;沒有量度的指示 | example-only |
| V3 | unknown | v1 | coder-a | 字幕失敗;未觀察到編碼 | example-only |
| V4 | unknown | v1 | coder-a | 字幕失敗;未觀察到編碼 | example-only |
| V5 | unknown | v1 | coder-a | 字幕未核對;未觀察到編碼 | example-only |
片段表:
| selected_video_key | startSeconds | endSeconds | text | source_observation |
|---|---|---|---|---|
| V1 | 0.5 | 2.5 | I measure the water before I pour it | 已核對的字幕證據,支持編碼 1 |
| V1 | unknown | unknown | unknown | 第二個量度片段;只作額外證據;這裡未設定時間 |
| V2 | unknown | unknown | I pour water into the tray | 已核對的字幕證據,支持編碼 0 |
| V5 | unknown | unknown | unknown | 字幕漏了一句已說出的量度語句;這裡未設定字詞 |
V3 和 V4 沒有片段行。它們的結果文字是空白。不要在 0 秒加一個片段。零會看起來像真實時間。缺失的時間保持未知。
第一個 V1 片段在 2.5 秒結束,在 0.5 秒開始。2.5 減 0.5 是 2.0 秒。這個長度用 `endSeconds` 和 `startSeconds`。第二個 V1 片段也支持量度編碼。它不產生第二條影片。V1 仍是一條已編碼的影片。被數算的單位是影片。
已核對且合資格的影片:2。編碼為 1 的影片:1。1 / 2 = 0.5,即 50%。已選清單仍有 5 條影片。1 / 5 = 0.2,即 20%。不要報告 20%。V3、V4 和 V5 沒有被核實為編碼 0。未知不是零。
五條已選影片的結果次數:2 條已核對且合資格,2 條失敗,1 條核對未完成。兩個失敗的狀態不同。一個是 `no_public_captions`。另一個是 `language_unavailable`。
假設你把這五個輸入提交了一次。假設沒有重複。下面的預期帳目數字是根據這個虛構例子計算出來的。這不是真實執行的回執。`inputsReceived` 會是 5。`resultRows` 會是 5。`billableTranscriptRows` 會是 3。`nonBillableResultRows` 會是 2。`duplicateVideosSkipped` 會是 0。`statusCounts` 會顯示 `succeeded` 3、`no_public_captions` 1,以及 `language_unavailable` 1。你的真實執行必須對照你實際收到的帳目來檢查。
這個例子顯示,額外片段不會增加影片。它也顯示合資格分母。它不顯示一組真實影片。它不顯示字幕準確率。它不顯示這些編造行以外的效應。
已知 V1 片段的平面 JSON 資料結構是:
{
"videoId": "video-v1",
"segments": [
{
"startSeconds": 0.5,
"endSeconds": 2.5,
"text": "I measure the water before I pour it"
}
]
}那個物件是給攤平步驟用的虛構例子。攤平之後,上面的片段表是編碼副本。影片表仍是計數副本。
來源與延伸閱讀
作者 Chronometrica · 更新日期
返回頂端 ↑

