- HTML
HTML video・audioタグの使い方|自動再生されない原因と対処
videoタグは動画を、audioタグは音声を、プラグインなしでページに埋め込むためのHTML要素です。自動再生したいときは、videoにautoplay muted playsinlineの3つをそろえて書くのが基本形です。 音が出る状態での自動再生は、利用者がページを操作するまでブラウザーが止める決まりになっているためです。
この記事では、videoとaudioの属性を早見表にまとめたうえで、「autoplayを書いたのに再生されない」を原因別に再現します。Playwright 1.56.0 に同梱の Chromium 141 で実際に動かし、コンソールに出たエラー文と、直したあとの結果をセットで載せています。 形式別のブラウザー対応、ChromeとSafariとiOSの自動再生ポリシーの違いも表で確認できます。
video・audioタグの早見表
すぐ使える書き方
| やりたいこと | 書き方 |
|---|---|
| 操作パネル付きで動画を置く | <video src="movie.mp4" controls></video> |
| 背景動画のように自動で流す | <video src="movie.mp4" autoplay muted loop playsinline></video> |
| 複数の形式を用意する | videoの中に<source src type>を並べる |
| 再生前の画像を出す | poster="thumb.jpg" |
| 音声を置く | <audio src="voice.mp3" controls></audio> |
| ボタンで再生する | クリックの処理の中でmedia.play() |
| 自動再生できたか調べる | play()が返すPromiseをcatchする |
属性の早見表
| 属性 | video | audio | はたらき |
|---|---|---|---|
src |
○ | ○ | ファイルの場所。sourceを使うなら不要 |
controls |
○ | ○ | 再生ボタンや音量などの操作パネルを出す |
autoplay |
○ | ○ | 読み込めたら自動で再生する(条件あり) |
muted |
○ | ○ | 最初から消音にする |
loop |
○ | ○ | 終わったら最初から繰り返す |
preload |
○ | ○ | 先読みの量。none / metadata / auto |
playsinline |
○ | ― | iPhoneで全画面にせず、その場で再生する |
poster |
○ | ― | 再生前に見せる画像 |
width / height |
○ | ― | 表示サイズ。書いておくと読み込み中に場所が確保される |
crossorigin |
○ | ○ | 別オリジンのファイルを読むときの設定 |
controlslist |
○ | ○ | 操作パネルの一部を隠す(Chromium系の機能) |
disablepictureinpicture |
○ | ― | ピクチャーインピクチャーのボタンを出さない |
audioにcontrolsを書かないと、画面には何も表示されません。audioは「controlsを付けて見せる」か「JavaScriptから鳴らす」のどちらかになります。
自動再生されない原因の早見表
| 原因 | 見分け方 | 直し方 |
|---|---|---|
mutedがない |
エラーは出ず、止まったまま。play()ならNotAllowedError |
mutedを付ける、またはクリック後に再生 |
playsinlineがない |
iPhoneで全画面再生になる、または始まらない | playsinlineを付ける |
| パスが違う | コンソールに404、NotSupportedError |
srcのパスを直す |
| 形式に対応していない | NotSupportedError、error.codeが4 |
対応形式をsourceで追加する |
typeの書き間違い |
エラーなしで何も読み込まれない | typeを正しいMIMEタイプにする |
| audioを自動再生している | mutedを付けても止まったまま(Chromium 141) |
ボタン操作で再生する |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「HTML video・audioタグの使い方|自動再生されない原因と対処」
videoタグの基本の書き方
いちばん短い形
<video src="movie.mp4" controls width="640" height="360"></video>
controlsを付けると、ブラウザーが用意した再生ボタン・シークバー・音量・全画面のパネルが表示されます。widthとheightを書いておくと、動画を読み込む前から場所が確保され、読み込み後にページがずれにくくなります。
複数の形式を用意するsource
ブラウザーによって再生できる形式が異なるため、sourceで複数のファイルを並べられます。上から順に調べ、最初に再生できそうなものが使われます。
<video controls width="640" height="360" poster="thumb.jpg">
<source src="movie.webm" type="video/webm">
<source src="movie.mp4" type="video/mp4">
<p>お使いのブラウザーでは動画を再生できません。<a href="movie.mp4">ダウンロードはこちら</a></p>
</video>
typeにはMIMEタイプを書きます。ブラウザーはtypeを見て、再生できない形式ならダウンロードせずに次へ進みますvideoの中に書いた文章は、video要素そのものに対応していない環境でだけ表示されます
画面幅に合わせる
<video src="movie.mp4" controls class="movie"></video>
.movie {
max-width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
max-width: 100%とheight: autoで、スマートフォンでも横幅に収まります。aspect-ratioを書いておくと、読み込み前でも比率どおりの高さが確保されます。
字幕を付けるtrack
<video src="movie.mp4" controls>
<track kind="subtitles" src="ja.vtt" srclang="ja" label="日本語" default>
</video>
字幕はWebVTT形式(拡張子.vtt)のテキストファイルで用意します。音を出せない場所で見る人や、聞き取りにくい人にも内容が伝わります。(trackの表示は今回は未実行です。)
audioタグの基本の書き方
<audio src="voice.mp3" controls></audio>
複数形式を並べる書き方はvideoと同じです。
<audio controls preload="metadata">
<source src="voice.ogg" type="audio/ogg">
<source src="voice.mp3" type="audio/mpeg">
</audio>
| videoとの違い | 内容 |
|---|---|
| 表示 | controlsがなければ何も表示されない |
| 使えない属性 | poster、width、height、playsinline |
| 自動再生 | 音を出すことが目的なので、操作なしの自動再生はほぼ通らない |
| JavaScriptで作る | new Audio("voice.mp3")で要素を作れる |
効果音のように画面に出さず鳴らす場合は、ボタンのクリックの中で再生します。
<button id="se">効果音を鳴らす</button>
<script>
const audio = new Audio("click.mp3");
document.querySelector("#se").addEventListener("click", () => {
audio.currentTime = 0;
audio.play();
});
</script>
形式別のブラウザー対応表
動画
| 形式(コンテナ) | おもなコーデック | MIMEタイプ | 対応の目安 |
|---|---|---|---|
| MP4 | H.264 + AAC | video/mp4 |
主要ブラウザーすべてで再生できる |
| WebM | VP8 / VP9 / AV1 + Opus / Vorbis | video/webm |
主要ブラウザーで再生できる。Safariは版によって対応範囲が異なる |
| Ogg | Theora + Vorbis | video/ogg |
対応が限られる(下の実測では空文字) |
| QuickTime | 各種 | video/quicktime |
Webでの利用には向かない。MP4に変換する |
音声
| 形式 | MIMEタイプ | 対応の目安 |
|---|---|---|
| MP3 | audio/mpeg |
広く再生できる。迷ったらこれ |
| AAC(MP4 / M4A) | audio/mp4 |
広く再生できる |
| Ogg(Vorbis / Opus) | audio/ogg |
Chrome・Firefoxで再生できる。Safariは18.4以降でOpus / Vorbisに対応 |
| WebM(Opus) | audio/webm |
Chrome・Firefoxで再生できる。Safariは18.4以降でOpus / Vorbisに対応 |
| WAV | audio/wav |
広く再生できるが、無圧縮でファイルが大きい |
| FLAC | audio/flac |
可逆圧縮。音質を保ちたいときに |
MDNの「メディアコンテナー形式」のページでは、MP4とWebMがどちらも主要ブラウザーで対応とされ、SafariについてはWebMとOggに入ったOpus・Vorbisが18.4以降(macOS 15.4、iOS 18.4以降)で対応した、と注記されています(今回このページを開いて確認)。MP3・WAV・FLACの対応状況は一般に知られた内容をもとに書いており、個別の版までは今回確認していません。
迷ったときは「動画はMP4(H.264 + AAC)、音声はMP3」を基本にし、容量を抑えたいときにWebMを先頭のsourceに足す、という組み合わせが扱いやすいです。
canPlayTypeで手元のブラウザーを調べる
canPlayTypeにMIMEタイプを渡すと、再生できそうかを文字列で返します。probably(おそらく可)、maybe(コーデック次第)、空文字(不可)の3通りです。
const v = document.createElement("video");
const a = document.createElement("audio");
console.log(v.canPlayType('video/webm; codecs="vp9, opus"'));
console.log(a.canPlayType("audio/mpeg"));
検証用のChromium 141(Playwright同梱)での結果です。
video/mp4 -> "maybe"
video/mp4; codecs="avc1.42E01E, mp4a.40.2" -> ""
video/webm -> "maybe"
video/webm; codecs="vp8, vorbis" -> "probably"
video/webm; codecs="vp9, opus" -> "probably"
video/mp4; codecs="av01.0.05M.08" -> "probably"
video/ogg; codecs="theora" -> ""
video/quicktime -> ""
audio/mpeg -> "probably"
audio/mp4; codecs="mp4a.40.2" -> ""
audio/ogg; codecs="vorbis" -> "probably"
audio/ogg; codecs="opus" -> "probably"
audio/webm; codecs="opus" -> "probably"
audio/wav -> "maybe"
audio/flac -> "probably"
audio/aac -> ""
H.264とAACが空文字になっているのは、検証に使ったのがオープンソース版のChromiumで、これらのコーデックを含まないビルドだからです。 製品版のGoogle Chromeでは再生できます。この違いを利用して、後半で「形式に対応していないとき」のエラーを再現します。コーデックまで書かないvideo/mp4がmaybeを返している点にも注目してください。maybeは「入れ物は知っているが、中身しだい」という意味です。
自動再生の基本形と、効く条件
基本形はautoplay muted playsinline
<video src="movie.mp4" autoplay muted loop playsinline></video>
| 属性 | 役割 |
|---|---|
autoplay |
自動再生を指示する |
muted |
消音にして、自動再生の条件を満たす |
playsinline |
iPhoneでその場(インライン)で再生する |
loop |
繰り返す(背景動画向け) |
検証の前提
Chromium 141を、デスクトップ版Chromeの標準と同じ自動再生ポリシー(--autoplay-policy=document-user-activation-required)で起動し、ページを開いてから何も操作せずに1.2秒後の状態を記録しました。オプションなしで起動した場合も、A1・A2は同じ結果でした。動画はffmpegで作った3秒のWebM(VP8 + Vorbis)、音声は3秒のMP3です。
検証用のHTMLの末尾に、次のスクリプトを入れています。
<script>
setTimeout(() => {
const m = document.querySelector("video,audio");
console.log("STATE " + JSON.stringify({
paused: m.paused,
currentTime: +m.currentTime.toFixed(2),
muted: m.muted,
readyState: m.readyState,
error: m.error ? m.error.code + " " + m.error.message : null,
}));
}, 1200);
</script>
pausedがfalseでcurrentTimeが進んでいれば、自動再生できています。以降の出力は、見やすさのために一部の項目を省き、長い行は折り返して載せています。
属性の組み合わせごとの結果
| 番号 | HTML | paused | currentTime | 結果 |
|---|---|---|---|---|
| A1 | <video src="sample.webm" autoplay> |
true | 0 | 止まったまま |
| A2 | <video src="sample.webm" autoplay muted> |
false | 1.13 | 再生された |
| A3 | <video src="sample.webm" autoplay muted playsinline loop> |
false | 1.13 | 再生された |
| A4 | <video src="silent.webm" autoplay>(音声トラックなしの動画) |
true | 0 | 止まったまま |
| A5 | <audio src="sample.mp3" autoplay> |
true | 0 | 止まったまま |
| A6 | <audio src="sample.mp3" autoplay muted> |
true | 0 | 止まったまま |
A1とA2の出力をそのまま載せます。
== A1 video autoplay のみ(音あり)
STATE {"paused":true,"currentTime":0,"muted":false,"readyState":4,"error":null}
== A2 video autoplay muted
STATE {"paused":false,"currentTime":1.13,"muted":true,"readyState":4,"error":null}
ここからわかることは3つあります。
autoplay属性だけでは、エラーも警告も出ずに止まったままになる。 A1はreadyStateが4(十分に読み込めている)でerrorもnullです。読み込みは済んでいるのに再生だけが始まらない、という状態です- 音声トラックのない動画でも、
muted属性がないと再生されなかった(A4)。 「無音の動画だからmutedはいらない」とは考えず、属性としてmutedを書いておくのが確実です - audioは
mutedを付けても自動再生されなかった(A6)。 手元のChromium 141では、消音での自動再生が通ったのはvideoだけでした
JavaScriptのplay()とNotAllowedError
操作なしでplay()を呼ぶとどうなるか
play()はPromise(結果があとで届く仕組み)を返します。再生が始まれば成功、止められればエラーとして届きます。ページの読み込み直後に、操作なしで呼んでみます。
<video src="sample.webm"></video>
<script>
window.addEventListener("load", async () => {
const m = document.querySelector("video");
try {
await m.play();
console.log("play() 成功 paused=" + m.paused);
} catch (e) {
console.log(e.name + ": " + e.message);
}
});
</script>
実行結果(Chromium 141):
== C1 play() 操作なし・音あり video
NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
== C2 play() 操作なし・muted video
play() 成功 paused=false
== C3 play() 操作なし audio
NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
NotAllowedError: play() failed because the user didn't interact with the document first.は、「利用者がまだページを操作していないので、音の出る再生を止めました」という意味です。 ファイルやコードの書き間違いではなく、ブラウザーの決まりによるものなので、対処は「消音にする」か「操作のあとで再生する」のどちらかになります。
tryとcatchを書かずにplay()だけを呼ぶと、同じ文面が捕まえられていないエラーとして報告されます(検証ではpageerrorとして同じ文面を受け取りました)。開発者ツールのコンソールでは、一般に先頭へUncaught (in promise)が付いた形で表示されます。
対処1:mutedを付ける
C2のとおり、mutedを付けたvideoは操作なしでもplay()が通ります。
対処2:クリックのあとで再生する
ボタンのクリックの中でplay()を呼ぶと、音ありでも再生できます。
<button id="btn">再生</button>
<video src="sample.webm"></video>
<script>
document.querySelector("#btn").addEventListener("click", async () => {
const m = document.querySelector("video");
try {
await m.play();
console.log("play() 成功 paused=" + m.paused + " muted=" + m.muted);
} catch (e) {
console.log(e.name + ": " + e.message);
}
});
</script>
== C9 クリックしてから play() 音あり
play() 成功 paused=false muted=false
対処3:音ありを試し、止められたら消音に切り替える
「できれば音ありで、無理なら消音で流す」という作りです。
<video src="sample.webm" autoplay loop playsinline></video>
<script>
const v = document.querySelector("video");
window.addEventListener("load", async () => {
try {
await v.play();
console.log("音ありで再生");
} catch (e) {
if (e.name === "NotAllowedError") {
v.muted = true;
await v.play();
console.log("ミュートに切り替えて再生 paused=" + v.paused);
} else {
console.log(e.name);
}
}
});
</script>
== C11 フォールバック付き
ミュートに切り替えて再生 paused=false
消音で流してから、ボタンで音を出す
消音で自動再生している動画のmutedを、操作なしでスクリプトから外すとどうなるかも確かめました。
== C7 muted自動再生中に操作なしで muted=false
解除前 paused=false
[warning] Unmuting failed and the element was paused instead because the user didn't interact with the document before. https://goo.gl/xX8pDD
解除後 paused=true muted=false
操作なしで消音を解除すると、音は出ずに動画が一時停止します。 コンソールにはUnmuting failed and the element was paused insteadという警告が出ます。消音の解除は、ボタンのクリックの中で行います。
<button id="btn">音を出す</button>
<video src="sample.webm" muted autoplay loop playsinline></video>
<script>
const v = document.querySelector("video");
document.querySelector("#btn").addEventListener("click", () => {
v.muted = false;
});
</script>
== C10 クリックで muted 解除
解除後 paused=false muted=false
クリックのあとなら、再生は続いたまま音が出ます。
再生できないときの原因別の再現
ここからは自動再生ポリシー以外の原因です。条件をそろえるため、すべてautoplay mutedを付けています。
パスの誤り
srcのパスが違っていて、サーバーが404を返す場合です。
<video src="movie/sample.webm" autoplay muted></video>
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
{"paused":true,"currentTime":0,"readyState":0,"networkState":3,
"error":"4 MEDIA_ELEMENT_ERROR: Format error","currentSrc":"/movie/sample.webm"}
この状態でplay()を呼ぶと、次のエラーになります。
NotSupportedError: The element has no supported sources.
NotSupportedError: The element has no supported sources.は、「再生できるファイルが1つも見つからなかった」という意味です。 パスの誤りでも形式の非対応でも同じ文面になるので、コンソールに404の行が一緒に出ていないかを見て切り分けます。error.codeの4はMEDIA_ERR_SRC_NOT_SUPPORTEDを表します。「Format error」と表示されますが、原因はファイルが見つからないことでした。開発者ツールのネットワークのタブで、動画ファイルの行が200または206になっているかを確かめるのが近道です。
形式に対応していない
検証用のChromiumはH.264を含まないため、MP4を直接指定すると再生できません。
<video src="sample.mp4" autoplay muted></video>
{"paused":true,"currentTime":0,"readyState":0,"networkState":3,
"error":"4 DEMUXER_ERROR_NO_SUPPORTED_STREAMS: FFmpegDemuxer: no supported streams"}
play()の結果はパスの誤りと同じNotSupportedError: The element has no supported sources.でしたが、video.error.messageを見るとDEMUXER_ERROR_NO_SUPPORTED_STREAMS(対応している映像・音声が中に入っていない)と、理由が区別できます。 拡張子が.mp4でも、中のコーデックがH.265などブラウザーの対応していないものだと同じ状態になります(H.265のファイルでの確認は未実行です)。
直し方は、sourceで別の形式を足すことです。
<video autoplay muted playsinline>
<source src="sample.mp4" type="video/mp4">
<source src="sample.webm" type="video/webm">
</video>
{"paused":false,"currentTime":1.13,"readyState":4,"error":null,"currentSrc":"/sample.webm"}
1つ目のMP4が読めなかったあと、2つ目のWebMに切り替わって再生されました。currentSrcで、実際に使われたファイルを確認できます。
MIMEタイプの誤り
MIMEタイプの誤りには、サーバーが返すContent-Typeヘッダーと、sourceのtype属性の2か所があります。
| 番号 | 状況 | 結果(Chromium 141) |
|---|---|---|
| B2 | サーバーのContent-Typeがtext/plain |
再生された |
| B3b | サーバーのContent-Typeがapplication/octet-stream |
再生された |
| B4 | sourceのtypeがvideo/mp4(中身はWebM) |
再生された |
| B4b | sourceのtypeがvideo/abc(存在しない形式) |
読み込まれず、エラーも出ない |
== B4b source の type が存在しない形式
{"paused":true,"currentTime":0,"readyState":0,"networkState":3,"error":null,"currentSrc":""}
Chromium 141は、Content-Typeが違っていてもファイルの中身を見て再生しました。一方、type属性にブラウザーの知らない形式を書くと、ファイルを取りにも行かず、errorもnullのまま何も起きません(currentSrcが空)。 type="video/mp4"をtype="mp4"やtype="video/mpeg4"のように書き間違えると、この状態になります。
Content-Typeの扱いはブラウザーごとに異なり、Safariは正しいContent-TypeやRangeリクエスト(ファイルの一部分だけを取り寄せる仕組み)への対応をサーバーに求めることが一般に知られています(Safariでの確認は未実行です)。サーバー側では次の対応をそろえておくと、どのブラウザーでも通りやすくなります。
| 拡張子 | Content-Type |
|---|---|
.mp4 |
video/mp4 |
.webm |
video/webm |
.mp3 |
audio/mpeg |
.ogg(音声) |
audio/ogg |
.wav |
audio/wav |
.m4a |
audio/mp4 |
sourceがすべて読めなかったとき
sourceを使う書き方では、エラーの出る場所が変わります。
<video muted autoplay>
<source src="a.webm" type="video/webm">
<source src="b.mp4" type="video/mp4">
</video>
<script>
const v = document.querySelector("video");
v.addEventListener("error", () => console.log("video error event"));
v.querySelectorAll("source").forEach((s) =>
s.addEventListener("error", () => console.log("source error:", s.getAttribute("src"))));
</script>
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
source error: a.webm
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
source error: b.mp4
{"networkState":3,"error":null,"readyState":0}
sourceを使っているときは、videoではなく各sourceでerrorイベントが発生し、video.errorはnullのままです。 「再生できませんでした」という表示を出したいときは、最後のsourceのerrorイベントか、video.networkStateが3(NETWORK_NO_SOURCE)になっていることで判定します。
読み込みの進み具合を見るイベント
どこまで進んで止まっているかは、イベントの順番でわかります。消音の自動再生で、3秒の動画を最後まで流したときの記録です。
loadstart readyState=0
loadedmetadata readyState=1
loadeddata readyState=4
canplay readyState=4
canplaythrough readyState=4
play readyState=4
playing readyState=4
pause readyState=4
ended readyState=4
| 止まった場所 | 考えられる原因 |
|---|---|
loadstartのあと何も来ない |
パスの誤り、サーバーの応答なし |
loadedmetadataまで来る |
ファイルは読めている。長さやサイズ(duration、videoWidth)が取れる |
canplayまで来るがplayが来ない |
自動再生ポリシーで止まっている |
playは来るがplayingが来ない |
データ待ち(通信が細い) |
切り分けの流れ
flowchart TD
A[再生されない] --> B{コンソールに404がある}
B -->|はい| C[パスを直す]
B -->|いいえ| D{video.error や NotSupportedError が出ている}
D -->|はい| E[形式を確認し source を追加する]
D -->|いいえ| F{currentSrc が空}
F -->|はい| G[source の type を直す]
F -->|いいえ| H{NotAllowedError または paused のまま}
H -->|はい| I[muted を付ける またはクリック後に再生する]
H -->|いいえ| J[iPhone なら playsinline を確認する]
Chrome・Safari・iOSの自動再生ポリシーの違い
各ブラウザーの公開情報(Chrome for Developersの自動再生ポリシーの記事、WebKitブログのiOS向け動画ポリシーの記事、MDNの自動再生ガイド。いずれも今回開いて確認)をもとに整理しました。
| 観点 | Chrome(デスクトップ) | Chrome(Android) | Safari(iOS / iPadOS) |
|---|---|---|---|
| 消音の自動再生 | 常に許可 | 常に許可 | 許可(音声トラックなし、またはmuted) |
| 音ありの自動再生 | 操作のあと、またはMEIが基準を超えたサイト | 操作のあと、またはホーム画面に追加したサイト | 利用者の操作が必要 |
playsinline |
不要(もともとインライン) | 不要 | iPhoneでは必要。ないと全画面での再生になる |
| 画面外のとき | ― | ― | autoplayは画面に見えているときだけ始まり、見えなくなると一時停止 |
| 操作なしで消音を解除 | 一時停止する(上のC7) | ― | 一時停止する |
| iframeの中 | 親ページがallow="autoplay"で許可を渡せる |
同左 | ― |
止められたときのplay() |
NotAllowedErrorで拒否 |
同左 | 同左(MDNの記載) |
補足です。
- MEI(Media Engagement Index) は、Chromeがサイトごとに記録している「音ありの動画をどれだけ見たか」の指標です。Chromeの記事では、消音でなく、タブが前面にあり、動画が200×140ピクセルより大きく、7秒を超えて再生された場合に数えられる、と説明されています。開発中の自分のパソコンでは音ありで自動再生できたのに、ほかの人の環境では止まる、という差はこの仕組みから生まれます
- iOSの記事では、
autoplay属性による再生は画面内に見えているときだけ始まり、play()メソッドによる再生は画面外でも可能、と区別されています - MDNのガイドは、Safariでの自動再生には
playsinlineが必要と書き、autoplay muted playsinlineの3つをそろえた例を示しています - macOS版Safariは、サイトごとに自動再生の可否を利用者が設定できることが一般に知られています(今回、該当ページは開いておらず、動作も未実行です)
- Firefoxは、MDNのガイドによると設定
media.autoplay.defaultの既定が0(許可)で、音ありの自動再生を止めるかどうかを利用者が設定で選べます
iPhoneやSafariでの挙動は、この記事では実機での確認ができていません(未実行)。 上の表は公開情報をもとにしているので、公開前に実機で確かめることをおすすめします。
iframeで埋め込むとき
別のオリジンのページをiframeで埋め込み、その中で自動再生させたいときは、親ページ側で許可を渡します。
<iframe src="https://media.example.com/player.html" allow="autoplay; fullscreen"></iframe>
同じオリジンのiframeでは、allowなしでも消音の自動再生が通りました(Chromium 141で確認)。別オリジンでの確認は未実行です。
そのまま使える完成形
背景動画
<video class="hero" autoplay muted loop playsinline poster="hero.jpg" preload="auto">
<source src="hero.webm" type="video/webm">
<source src="hero.mp4" type="video/mp4">
</video>
.hero {
width: 100%;
height: 60vh;
object-fit: cover;
}
@media (prefers-reduced-motion: reduce) {
.hero { display: none; }
}
posterを書いておくと、再生が始まらなかった場合にも画像が残ります。prefers-reduced-motionは「動きを減らす」設定をしている人向けの配慮です(CSSの表示は未実行です)。
音ありで見せたい動画
<video id="intro" controls playsinline preload="metadata" poster="intro.jpg" width="640" height="360">
<source src="intro.mp4" type="video/mp4">
</video>
音を聞いてほしい動画は、自動再生にせずcontrolsで利用者に再生してもらう形が、どのブラウザーでも同じように動きます。preload="metadata"にすると、再生前の通信量を抑えられます。
preloadの選び方
| 値 | 先読みする量 | 向いている場面 |
|---|---|---|
none |
何も読まない | 動画が多いページ、見られるかわからない動画 |
metadata |
長さやサイズだけ | 通常の動画 |
auto |
ブラウザーに任せて多めに | すぐ再生される動画 |
autoplayを付けた場合は、再生のために読み込みが行われるのでpreloadの指定よりautoplayが優先されます。
よくある質問
Q. autoplayを書いたのに自動再生されません。まず何を確認すればよいですか?
A. mutedが付いているかを確認します。音の出る状態では、利用者がページを操作するまで自動再生は始まりません。iPhoneも対象ならplaysinlineも加え、autoplay muted playsinlineの3つをそろえます。
Q. 音ありで自動再生する方法はありますか? A. 利用者の操作なしに確実に音を出す方法はありません。消音で再生を始めて「音を出す」ボタンを用意するか、再生ボタンを押してもらう形にします。
Q. NotAllowedErrorとNotSupportedErrorの違いは?
A. NotAllowedErrorは自動再生ポリシーで止められたとき、NotSupportedErrorは再生できるファイルが見つからないとき(パスの誤りや形式の非対応)に出ます。前者はmutedかクリック後の再生で、後者はパスと形式の見直しで直します。
Q. audioタグでBGMを自動で流せますか?
A. 手元のChromium 141では、mutedを付けてもaudioの自動再生は始まりませんでした。BGMは、再生ボタンを用意して利用者に押してもらう形にします。
まとめ
- 自動再生の基本形は
autoplay muted playsinline。mutedがないと、エラーも出ずに止まったままになる play()がNotAllowedErrorで拒否されたら自動再生ポリシーが理由。 消音にするか、クリックのあとで再生するNotSupportedErrorはパスか形式が理由。 コンソールの404とvideo.error.messageで切り分けるsourceのtypeを書き間違えると、エラーなしで何も読み込まれない。currentSrcが空かどうかで気づける- 動画はMP4(H.264 + AAC)、音声はMP3を基本に、
sourceで複数形式を並べる - 操作なしで
mutedを外すと一時停止する。 音を出す切り替えはボタンのクリックの中で行う - audioは
controlsを付けるか、クリックの中でplay()を呼ぶ
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「HTML video・audioタグの使い方|自動再生されない原因と対処」
株式会社RJCでは、HTMLの動画・音声の扱い方やブラウザーの仕組みを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。