この記事は2026年9月10日に執筆されたものです。
皆さんは、思いがけず目にした遠い国の動画から、意外なアイデアを得たことはありますか?
Inflearnは、言語の壁を越えて幅広い知識をお届けするために、
字幕、吹き替えに続いて、動画の画面にある文字まで翻訳する動画画面翻訳機能を準備しています。
最近Inflearnで公開したDeNA × AI Day 2026をはじめ、今後は各国のカンファレンス動画や講座もご覧いただけるようになります。すでにいくつかの講座には画面翻訳機能が適用されており、新たに追加される一部の講座にも実験的に適用する予定です。
そこで本記事では、この機能を実装するにあたって検討した内容を共有します。
結果の例
適用前
適用後
元動画: DeNA × AI Day 2026、「AI×業務改革 AI Workspaceプロジェクトの Agent活用最前線」
翻訳された動画を表示する方法
動画の画面内の文字を翻訳する機能は、どのように実装できるでしょうか?
まず翻訳対象の動画が必要で、その画面に表示されている原文を翻訳後の文字に置き換えることになるでしょう。
私たちは、動画の文字を翻訳版に置き換えて表示するために、
あらかじめ用意した翻訳を再生中の画面の上に重ねて描画するオーバーレイ方式を選びました。
元の動画は従来どおりに再生しつつ、文字の背後の領域だけを周囲の背景と同じ色のボックスで覆って原文を隠します。そして、その上の同じ位置に翻訳された文字を載せるという仕組みです。
元の動画の上に、背景色のボックスと翻訳テキストの2つのレイヤーを重ねて描画します。
この方式なら、動画のエンコーディングとは関係なく新しい言語を簡単に追加できます。また、誤訳を見つけたり翻訳パイプラインを改善したりしたときも、データを修正するだけですぐに反映されるので、少ないコストで柔軟に品質を磨いていけます。
翻訳されたテキストデータだけを別途レスポンスとして返すので、サーバーとクライアントのどちらもネットワーク転送量の負担が小さいことも大きな利点でした。
Google レンズでも、原文の文字が背景色で隠され、その位置に翻訳された文字を重ねて表示します。Inflearnの画面翻訳も同じ原理です。ただし、かざした瞬間に応答しなければならないレンズとは異なり、動画を事前に解析しておくため処理時間の制約が少なく、品質をさらに最適化したり、誤りのある部分を事前に補正したりできるという違いがあります。
出典: https://blog.google
内部で生成する成果物は、JSON形式のデータです。
{
"events": [
{
"start": 12.0,
"end": 47.0,
"texts": [
{
"text": "Part 2. From RNN to Transformer",
"translations": { "ko": "제2부 RNN에서 Transformer까지" },
"bbox": [104, 216, 632, 258],
"bg_color": [16, 42, 67],
"text_color": [236, 240, 244]
}
]
}
]
}
events は画面構成が維持される時間区間で、各テキストは位置(bbox)、原文、言語ごとの翻訳、そして背景色と文字色を持ちます。テキストを1つのフラットな配列にする方法もありますが、時間区間(event)でまとめたのは、プレイヤーでのシークを最適化するためです。動画の特性上、画面が切り替わるときにすべてのテキストが一度に変わることが多いからです。
プレイヤーは再生時刻に対応するイベントを探し、動画の上に bbox の位置どおりに bg_color で塗りつぶしたボックスを敷き、その上に text_color で翻訳テキストを描画します。原文の文字は背景色のボックスに隠れ、同じ位置に翻訳が表示される仕組みです。
ここまでが、翻訳された動画を表示する方法でした。残る問題は、このJSONデータをどうやって作り出すかです。
テキスト抽出
動画は結局のところ静止した画面、つまりフレームの連続なので、まずは画面1枚を翻訳することから考えてみます。最初の構想は、次のようにシンプルなものです。
- 画面内のテキストをOCR(光学文字認識)で読み取る。
- 読み取ったテキストを翻訳する。
- 翻訳結果を元のテキストと同じ位置にオーバーレイする。
この3ステップだけでも、画面翻訳自体は動作します。
しかし実際にテストしてみると、自然な成果物を作るには、さらに2つの処理が必要でした。
A. 翻訳が不要なテキストは除外する
PPTや文書のような一般的な翻訳対象とは異なり、講座動画のドメインには特有の難しさがあります。画面に細かいUIテキストやコードが一緒に映ることです。
とても小さなボタンやコード、コマンド、ファイルパスまですべて翻訳すると、見た目の自然さを損ないがちです。画面翻訳の目的はユーザーが動画の内容を理解できるよう手助けすることにあるので、理解に必要なテキストは翻訳しつつ、視聴の妨げになる要素は最小限に抑える必要があります。
同じ単語でも、本文中にあれば翻訳対象で、コードブロック内にあれば対象外となるため、単純なルールだけでは区別できません。そこで、画面の文脈をある程度理解できるVLM(Vision Language Model、画像を入力として受け取り、言語で推論するモデル)にこの判断を任せました。
B. 段落を把握する
ほとんどのOCRは、テキストを行単位の断片として返します。現代のOCRは主にテキスト検出(detection)とテキスト認識(recognition)の2段階のパイプラインで構成されており、検出器が探すのが行単位だからです。
行単位の断片が問題になるのは、言語ごとの語順の違いのためです。1つの文が複数行にまたがっていると、語順の異なる言語に翻訳したときに、結果を元の行と1:1で対応させることができません。1つの段落を1つのブロックにまとめ、翻訳もそのブロックの位置に丸ごと描画してこそ、自然な対応が可能になります。
画像やPDFから画面構造を把握し、段落のレイアウトを判断するタスクは、Document Layout Analysisという分野ですでに研究されてきました。そこでまず既存のモデルを試してみましたが、動画翻訳に適用するには満足のいくものではありませんでした。ほとんどがPDF文書の画像で学習されたモデルなので、講座動画によく登場するWebサイトやターミナルの画面のように、文書の規格から外れたレイアウトではブロックを見当違いに分割してしまうようでした。
図はXY-Cut++ (arXiv:2504.10258)を参考
そこで、段落の判断もVLMに任せつつ、判断すべき要素を最小限に減らして精度を補うようにしました。1984年に提案されたXY Cutアルゴリズムで画面を大まかなブロックに先に切り分けておけば、VLMはそれらのブロックを段落としてまとめるかどうかだけを判断すればよくなります。
XY Cutは、画面の余白を手がかりに領域を横方向・縦方向に交互に再帰分割する方式です。座標計算だけで動作するので、コストは事実上かかりません。分割結果はツリー構造として残り、分割された領域を上から下へ、左から右へと順に訪問すると、その訪問順は人が読む順序とおおむね近くなります。そのおかげで、ブロック内の複数行を1つの段落としてつなげる際にも、別途並べ替えることなくそのまま使えます。
フレーム処理の最適化
ここまでは、画面1枚を処理するための検討でした。しかし、動画は画面1枚ではありません。1秒に1フレームずつサンプリングするだけでも1時間の動画なら3,600枚になるので、大量の動画をすべてこの方式で処理するのは負担が大きくなります。
毎フレームOCRとVLMを実行するとコストも問題になりますが、より大きな問題は一貫性です。同じスライドが画面に表示されている間も、フレームごとにOCRの結果がわずかに揺らぐと、再生中にオーバーレイがちらついてしまいます。
基本的な構造は、毎フレームOCRを実行してテキストボックスを取得し、各ボックスをVLMで判定するというものです。そこに、直前のフレームと重なる部分は再処理せず結果を再利用する方式を適用しました。新しいフレームの各テキストボックスは、以下の順序で判断・処理されます。
-
ピクセルベースの再利用
その領域のピクセルが直前のフレームとほぼ同じであれば、OCRもVLMも再実行せず、前回の判定をそのまま使います。静的なスライドの区間では、この処理だけで多くのフレームがスキップされます。 -
領域ベースの再利用
位置が少し変わっていても、既存の領域とのIoU(重なりの割合)が0.5以上かつテキストの類似度が0.85以上であれば、前回の判定を再利用します。画面がわずかにスクロールされたり、エンコーディングノイズがあったりするケースはこれで吸収されます。 -
自動除外
新規ボックスのうち、翻訳すべき文字がないもの(例: 数字と記号だけのボックス)はモデルを呼び出さずに除外します。 -
VLMによる判定
ここまで残った新規ボックスだけをVLMで処理します。
このとき、OCRには元のフレームをそのまま入力せず、再利用が確定した領域をマスキングして、OCRが新たに現れた文字だけを検出するようにしています。この構造のおかげで、VLMの呼び出しは画面が実際に変わった瞬間にしか発生しません。同じスライドが表示されている間は前回の結果がそのまま維持されるので、オーバーレイも安定して表示されます。
テキストの色の抽出
文字をどこに描画するかは決まったので、次はどの色で描画するかを考える必要があります。
背景の多くは単色に近いと仮定すれば、背景と文字の色は、ボックス内のピクセルの色の分布を計算することで簡単に得られます。ピクセルをサンプリングしたあと、RGB空間で色を似た2つのグループに分類しておけば、ピクセル数の多いグループを背景、少ないほうを文字と推定できるからです。文字は、ほとんどの場合、背景よりも占める面積が小さいですからね。
グループを分ける方式としては、k-means(k=2)を使います。k-meansは、データをk個の群、つまりk個のクラスターに分けるアルゴリズムです。このアルゴリズムは、おおよそ次のように動作します。
- まず、中心点をk個、ランダムな位置に置きます。
- 各点を、その点から最も近い中心点と同じグループに分類します。
- 次に、中心点を自分に属する点の平均位置に移動します。
- 中心点が動いたので、所属が変わる点が出てきます。
そのため2に戻り、所属が変わらなくなるまで2〜3を繰り返します。
こうした繰り返しのステップを経ると、近い点同士でまとまったk個のグループが安定して作られます。ここではピクセルのRGB値がそのまま3次元空間の座標になるため、色の似たピクセル同士を自然にまとめることができます。
単色背景のテキストボックスを1つ処理する場合、背景のピクセルと文字のピクセルが、上の図のようにそれぞれ固まります。この図では、白が背景、緑が文字色だと考えられます。
翻訳と最終結果
最後に残ったステップは翻訳です。翻訳は、画面の処理がすべて終わったあとに別途行います。前のステップで作ったJSONから原文テキストを集めて重複を取り除き、LLM(大規模言語モデル)にまとめて翻訳をリクエストしたあと、結果を各テキストに書き戻します。同じ文言が複数の画面に繰り返し登場しても、翻訳は1回で済みます。
講座画面のテキストはタイトルやラベルのような短い断片が多いため、断片だけを個別に翻訳すると用語がバラバラになりがちです。そこで、動画のタイトルなど画面の周辺テキストもプロンプトに一緒に含め、同じ用語が常に同じ訳になるようにしました。このとき、テキストは先ほどXY Cutで整理した読み順どおりに並べ、人が画面を読むのと同じ順序でLLMが文脈を把握できるようにしました。
以下は、ここまでの処理をすべて経た最終的な成果物です。これで、プレイヤーで画面の言語を選択すると、元の動画はそのまま再生されつつ、画面内の文字だけが選択した言語で上書きされて表示されます。
画面翻訳の適用前と適用後の例
おわりに
ここまで、Inflearnが動画画面翻訳機能を開発するなかで今も続けている検討のうち、これまでに整理できたものを紹介しました。最後に、簡単に振り返ってみます。
- 翻訳結果は動画にエンコードせず、元の画面の上に背景色のボックスと翻訳テキストを重ねて描画するオーバーレイ方式で表示します。
- 画面内のテキストはOCRで読み取り、翻訳対象の選別と段落のまとめは、XY CutとVLMの組み合わせで解決しました。
- フレーム間で重なる領域は前回の結果を再利用し、処理コストを減らすとともにオーバーレイのちらつきを防ぎました。
- 文字色と背景色はk-meansでピクセルを2つのグループに分けて抽出し、翻訳は画面の処理が終わったあとに周辺の文脈を含めてまとめてリクエストします。
もちろん、まだすべての画面を完璧に翻訳できるわけではありません。写真やグラデーションの上にある文字は、まだ仕上がりが不自然です。また、アニメーションで動く文字にはオーバーレイが追従しきれないこともあります。このように磨き込むべき部分がまだ多く残っているので、一つずつ改善していくつもりです。
学びが言語によって妨げられないように、そしてより多様な知識が共有され、届けられるように、Inflearnではさまざまな挑戦を続けていく予定です。
読んでいただき、ありがとうございました。
参考リンク

