# スタイルを変えられない字幕、変換で消える字幕

Source: https://easeweb.dev/learn/caption-quality
Topics: 画像とメディア > 字幕が読みやすく、動画を変換しても失われない (EN 301 549 7.1.3, 7.1.4, 7.1.5, 7.2.3)
The fix: どの変換でも、字幕と音声解説の音声をストリームのトラックとして引き継ぎます。そのうえで、ブラウザーに字幕を描かせて利用者のシステムの字幕の設定が効くようにするか、プレーヤーに字幕の大きさ、色、背景の設定を用意します。字幕と違う言語で話す動画には、字幕の音声も用意します。
Test with: caption settings, screen off, keyboard
References: https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf https://bitvtest.de/pruefschritt/bitv-20-web/bitv-20-web-7-1-3-erhaltung-von-untertiteln https://bitvtest.de/pruefschritt/bitv-20-web/bitv-20-web-7-1-4-untertitel-anpassungen https://bitvtest.de/pruefschritt/bitv-20-web/bitv-20-web-7-1-5-gesprochene-untertitel https://www.w3.org/WAI/media/av/player/ https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices https://developer.mozilla.org/en-US/docs/Web/API/TextTrack/cuechange_event https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

コーヒー豆の焙煎店の淹れ方の動画には、確認済みの字幕と音声解説の音声があり、独自のプレーヤーには音量の隣にCCとADのボタンがあります。それでも、まだ2つの問題が起きます。

プレーヤーは、店の見た目に合わせるため、字幕を自分で描いています。13ピクセル、ブランドの細い書体、白、背景の箱なしです。キッチンの台は明るい色で、その上の字幕は読みにくくなっています。パソコンの字幕の設定で黒地に黄色の大きな字幕を選んでいる人にも、同じ小さな白い文字が出ます。その設定が整えるのはブラウザーが描く字幕で、プレーヤー自身の箱の中の文字ではないからです。プレーヤーには字幕の設定がありません。

その後、動画プラグインに「高速ストリーミング」の選択肢が加わり、店はそれをオンにしました。どの動画も、スマートフォンですぐに始まるアダプティブストリームに変換し直されます。エンコーダーが取り込んだのは動画のファイルとその音声だけで、一緒にアップロードした字幕のファイルと音声解説の音声は含まれませんでした。ストリーミング版は再生できますが、CCとADのボタンでオンにするものがありません。

## 確認できる問題

WCAGは字幕の見た目についてほとんど述べておらず、変換で何が残るかは扱っていません。WCAGの1.2.2が求めるのは字幕があることだけで、ストリーミング版はこれも満たさなくなっています。それは[字幕のない動画と、確認されていない自動字幕](/ja/learn/video-captions)で説明しています。これらの要件はEN 301 549にあり、その表A.1が、EUのWebアクセシビリティ指令に対応する要件として、Webページに適用しています。

- 7.1.3「字幕の保持」：サイトが音声付きの動画を送信、変換、録画する場合、字幕のデータを保ち、字幕を引き続き同期して表示できるようにする。このサイトはアップロードを変換するので、その字幕を保つ必要があります。
- 7.2.3「音声解説の保持」：音声解説について同じことを求めます。
- 7.1.4「字幕の特性」：サイトが字幕を表示する場合、利用者が、色、書体、大きさ、背景、縁取りなど、字幕の見た目を自分の必要に合わせられる。映像に焼き込んだ字幕は変えられないため対象外です。
- 7.1.5「音声の字幕」：サイトが音声付きの動画を表示する場合、字幕のテキストをソフトウェアで読み取れない場合を除き、字幕を読み上げるモードを持つ。ドイツのBITVの試験は、話し声がサイトの主な言語ではなく、その言語の字幕があり、その言語の音声の版がない場合に適用しています。全盲の視聴者が字幕を音声で必要とするのは、その場合です。淹れ方の動画のナレーターは字幕と同じ言語で話すため、字幕を読み上げてもナレーションを繰り返すだけで、BITVはこの動画にはこの項目を適用しません。ただし、項目を文字どおりに読む監査人は、それでも求めることがあります。

ストリーミングへの変換は7.1.3と7.2.3を満たしていません。プレーヤーは、字幕の背景や自分の字幕のスタイルが必要なすべての利用者について、7.1.4に届いていません。設定がなく、システムの字幕の設定も届かないからです。ブラウザーの拡大表示や配色も数えるBITVの試験では、拡大表示でこの字幕が大きくなり、コントラスト テーマで色が変わるため、満たしていると判定されることもあります。それでも、背景を付けるものはありません。

## 利用者への影響

誰にでも同じ小さな白い文字が出て、誰にでもストリーミング版が届きますが、多くの視聴者は字幕をオンにしないため、店は気づきません。

## 自動チェックとAIの限界

これを扱うWCAGのルールはないため、axeなどWCAGの自動チェックは見ません。動画に字幕トラックのあるページは、再生するストリームに字幕がなくても通ります。EaseWebの診断はすべての動画を確認項目として挙げ、独自の操作部品を持つプレーヤーについては、利用者が字幕の大きさ、色、背景を変えられるかを人に確認するよう求めます。ストリームを元のファイルと比べることも、ストリームのマニフェストを開くことも、字幕の設定を試すこともしません。AIのコードアシスタントに「字幕をブランドに合わせて」と頼むと、書体、大きさ、色を固定で書きやすく、まさにこの状態になります。

## 修正前：1つのスタイルで描かれる字幕

```js player.js
// The player hides the browser's captions and draws each cue itself.
const track = video.textTracks[0];
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
  captionBox.textContent = track.activeCues[0]?.text ?? '';
});
```

```css player.css
.caption-box {
  position: absolute;
  bottom: 8%;
  width: 100%;
  font: 13px/1.3 "Brand Sans", sans-serif;
  color: #fff;
  text-align: center;
}
```

字幕はテキストなので、見た目を変えられるはずですが、プレーヤーは設定を用意せず、利用者のシステムの字幕の設定はプレーヤー自身の箱の中の文字には届きません。背景のない細い白い文字は、明るい映像の上では読みにくくなります。ブラウザーの拡大表示でページごと大きくなり、強制配色（コントラスト テーマ）では文字の色も変わりますが、背景を付けるものはありません。

## 修正前：変換で失われる字幕と音声解説

```m3u8 master.m3u8
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=2400000,RESOLUTION=1280x720
video/720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360
video/360p.m3u8
```

ストリームのプレイリストには、映像の2つのサイズと、その音声しかありません。元の動画と一緒にアップロードした字幕のファイルと音声解説の音声が入っていないため、このストリームのプレーヤーには、出す字幕も再生する音声解説もありません。

## 修正後：変換でトラックを保ち、字幕をブラウザーに描かせる

```m3u8 master.m3u8
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English",LANGUAGE="en",DEFAULT=YES,AUTOSELECT=YES,URI="audio/en.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English, described",LANGUAGE="en",AUTOSELECT=YES,CHARACTERISTICS="public.accessibility.describes-video",URI="audio/en-described.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",LANGUAGE="en",AUTOSELECT=YES,CHARACTERISTICS="public.accessibility.transcribes-spoken-dialog,public.accessibility.describes-music-and-sound",URI="subs/en.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=2400000,RESOLUTION=1280x720,AUDIO="audio",SUBTITLES="subs"
video/720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,AUDIO="audio",SUBTITLES="subs"
video/360p.m3u8
```

```js player.js
// The browser draws the captions, so the viewer's system caption style applies.
const track = video.textTracks[0];
track.mode = 'showing';
```

エンコードの処理が、字幕を字幕のレンディションとして、音声解説の音声を映像を説明するものと示した2つ目の音声のレンディションとして引き継ぐため、このストリームのどのプレーヤーも、両方を同期して出せます。自分の箱を持たないプレーヤーは字幕をブラウザーに任せ、Safariや、ChromeやEdgeなどChromiumを使うブラウザーでは、利用者のシステムの字幕のスタイルで描かれます。Firefoxは、少なくともmacOSではシステムの字幕の設定を読まないため、その利用者にはページのスタイルが出ます。また、設定があると知らない人は、プレーヤーからそれを見つけられません。

## 修正後：変換でトラックを保ち、プレーヤー自身の字幕の設定を用意する

```m3u8 master.m3u8
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English",LANGUAGE="en",DEFAULT=YES,AUTOSELECT=YES,URI="audio/en.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English, described",LANGUAGE="en",AUTOSELECT=YES,CHARACTERISTICS="public.accessibility.describes-video",URI="audio/en-described.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",LANGUAGE="en",AUTOSELECT=YES,CHARACTERISTICS="public.accessibility.transcribes-spoken-dialog,public.accessibility.describes-music-and-sound",URI="subs/en.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=2400000,RESOLUTION=1280x720,AUDIO="audio",SUBTITLES="subs"
video/720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,AUDIO="audio",SUBTITLES="subs"
video/360p.m3u8
```

```html player.html
<fieldset class="caption-settings">
  <legend>Captions</legend>
  <label>Size
    <select data-style="--cap-size">
      <option value="1">100%</option>
      <option value="1.5">150%</option>
      <option value="2">200%</option>
    </select></label>
  <label>Text
    <select data-style="--cap-colour">
      <option value="#fff">White</option>
      <option value="#ffde3b">Yellow</option>
    </select></label>
  <label>Background
    <select data-style="--cap-back">
      <option value="rgb(0 0 0 / 0.8)">Black</option>
      <option value="transparent">None</option>
    </select></label>
</fieldset>
```

```js player.js
// Each setting sets a style on the caption box, and is kept for the next video.
for (const field of document.querySelectorAll('[data-style]')) {
  const key = `captions${field.dataset.style}`;
  field.value = localStorage.getItem(key) ?? field.value;
  const apply = () => {
    captionBox.style.setProperty(field.dataset.style, field.value);
    localStorage.setItem(key, field.value);
  };
  field.addEventListener('change', apply);
  apply();
}

const track = video.textTracks[0];
track.mode = 'hidden';
track.addEventListener('cuechange', () => {
  captionBox.textContent = track.activeCues[0]?.getCueAsHTML().textContent ?? '';
});
```

```css player.css
.caption-box {
  position: absolute;
  bottom: 8%;
  left: 50%;
  translate: -50%;
  max-width: 90%;
  padding: 0.1em 0.4em;
  font: calc(var(--cap-size) * 1.25rem) / 1.3 system-ui, sans-serif;
  color: var(--cap-colour);
  background: var(--cap-back);
  white-space: pre-line;
  text-align: center;
}
```

ストリームは、もう1つの修正と同じくトラックを保ちます。プレーヤーは字幕を描き続けますが、利用者は、どのブラウザーでも、大きさ、文字の色、背景を選べます。初期値は、どんな映像の上でも読める、黒に近い箱に白い文字です。選んだ設定は次の動画でも使われます。これらの設定は、プレーヤーの設定メニューの、字幕の言語の隣に置いてください。

## どの方法を選ぶか

どちらも変換でトラックを保ち、字幕の見た目を変えられるようにします。プレーヤー自身の設定を使ってください。どのブラウザーでも働き、利用者が探す場所にあり、読みやすいスタイルから始まります。ブラウザーに描かせる方法では、少なくともmacOSのFirefoxの利用者には1つのスタイルしか届かず、ほかの人にも、OSの奥にある設定を知っていることを求めます。ブラウザーに描かせるほうが変更は小さく、ブラウザー標準の操作部品を使うプレーヤーなら妥当な選択です。

## 実装の判断

アップロード後に動画が通る道を、すべて確認します。

- この例のようなストリーミング用のエンコーダー：処理の設定で、字幕のファイルを字幕のレンディションに、音声解説の音声を音声のレンディションに、すべての言語について割り当て、出力されたマニフェストにそれが載っているか確認する。DASHのマニフェストでは、字幕と説明の役割を付けた、テキストと音声のアダプテーションセットになる。
- YouTubeやVimeoなどの動画サービス：そこで動画に字幕のファイルをアップロードし、埋め込みで選べるか確認する。新しく編集した版をアップロードし直すと、字幕を付け直さない限り、前の字幕は失われる。
- SNS用のファイルや短く編集した版：新しい動画なので、その長さに合わせた字幕が別に要る。映像に焼き込んだ字幕は、別の字幕ファイルが届かない場所にも、ファイルと一緒に届く。
- ウェビナーやサポートの通話など、サイトが録画するもの：ライブの字幕を録画と一緒に保存し、録画とともに出す。

字幕の見た目が伝えることも保ちます。EN 301 549は、位置、色、スタイルが意味を持つことがあると注記しています。画面上の文字を隠さないよう上に移した字幕や、話し手ごとの色などです。言葉は残しても位置を落とす変換は直し、利用者の設定は、大きさと色を変えても、避けていたものの上へ字幕を戻さないようにします。

全画面表示：プレーヤーが字幕を自分で描く場合は、video要素ではなく、プレーヤーのコンテナーを `requestFullscreen()` で全画面にします。そうしないと字幕の箱が取り残されます。ブラウザーが描く字幕は、動画に自然についていきます。

別の言語の動画：スペイン語のインタビューに英語の字幕を付けた動画のように、話し声が字幕と違う言語の場合、スペイン語が分からない全盲の視聴者には、字幕を音声で届ける必要があります。よりよい方法は、EN 301 549が別の音声トラックとして届けることを示している、字幕を録音した音声トラックで、音声解説の音声と同じように選べるようにします。プレーヤーに、初期状態ではオフの「字幕を読み上げる」選択肢を用意し、音声合成で字幕を1つずつ読み上げることもできます。`SpeechSynthesisUtterance` の `lang` をトラックから設定し、次の字幕が始まったら前の読み上げを止めて遅れないようにし、読み上げる間は元の音声を小さくします。音声合成は、端末にその言語の音声があるかに左右されます。字幕と同じ言語で話す動画には、どちらも用意する必要はありません。ナレーションに同じ言葉を重ねるだけです。

映像に焼き込んだ字幕は、何も変えることも読むこともできないため、7.1.4と7.1.5の対象外です。それは焼き込みだけに頼らない理由であって、これらの要件を避ける方法ではありません。CCとADのボタンをどこに置くかは、[字幕を設定メニューの奥に隠す動画プレーヤー](/ja/learn/caption-controls)で説明しています。

## 修正の確認

1. ストリーム、動画サービスの埋め込み、編集した版など、動画の変換後の各版を元の動画と並べて再生する。すべての言語の字幕と音声解説が選べて、話し声と同期している。
2. プレーヤーの設定と、システムの字幕の設定（Windows：アクセシビリティ、字幕。macOS：アクセシビリティ、聴覚サポート、字幕。macOS 27では「標準字幕とバリアフリー字幕」）で、黒地に黄色の大きな字幕を選ぶ。macOSでは、「ビデオの設定を優先」のチェックを外す。オンのままだと、ページ自身の字幕のスタイルが優先されることがある。対応するどのブラウザーでも字幕がプレーヤーの設定に従い、ブラウザーが字幕を描く場合はシステムの設定に従うか確認する。
3. 字幕と違う言語で話す動画をサイトが流す場合、画面を覆ってそれを再生し、字幕の音声をオンにする。どの字幕も出たときに字幕の言語で読み上げられるか、字幕を録音した音声トラックが代わりに流れる。
4. 全画面表示でも、選んだスタイルで字幕が出るか確認し、字幕の設定をキーボードだけで操作する。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。エンコーダー、プレーヤー、動画サービスを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。設定が役立つのは、字幕が正しくそろっているときだけです。文字の縁取りや別の書体など、この3つ以外の設定が必要な人もいます。動画を見る人と一緒に、動画が実際に再生されるプレーヤーやサービスで、一連の流れを確認してください。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
