こんにちは、エンジニアの藤野です。
HTMLへの動画の埋め込みにvideo要素が使われるようになって久しいですが、これをブラウザの機能を用いて印刷するとどのようになるかご存知でしょうか?
とあるお客様から「動画の再生中のシーンを印刷したい」という要望を受け、調査したところ、各ブラウザによって結果が異なることが分かりました。
本記事では各ブラウザの動作と、「再生中のシーンを印刷する」方法を紹介します。
各ブラウザでの動作
下記環境で動作を確認しました。
macOS Mojave 上の
- Firefox 67.0.4
- Google Chrome 75.0.3770.100
Windows 10 上の
- Edge
確認に用いたコードは下記のとおりです。
<!DOCTYPE html> <html> <head> </head> <body> <video controls id="v"> <source src="v.mp4" type="video/mp4"> Sorry, your browser doesn't support embedded videos. </video> </body> </html>
v.mp4
は、エッジデバイス上での画像認識で弊社岡田が投稿した「AndoroidでImage Classification」の動画ファイルです。
それでは各ブラウザでの動作を見ていきましょう。
Firefox
動画部分が真っ白になります。
ブラウザでの表示:
印刷時の表示:
Chrome
動画部分が真っ白になります。
ブラウザでの表示:
印刷時の表示:
ときどき表示できる場合もあったのですが、その条件は分かりませんでした。
Edge
実はEdgeでは再生中のシーンがそのまま印刷できます。 つまり、FirefoxとChromeで同様の動作を実装すればよいことになります。
ブラウザでの表示:
印刷時の表示:
実装の方針
Canvasは要素の作成時にvideo要素をソースとすることができます。
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
これを用いることで、video要素の現在の再生中の画像をcanvasとして表示できます。 そして、画面と印刷時でvideo要素とcanvas要素の表示を切り替えることで、再生中のシーンを印刷します。
canvasへの表示
drawImageメソッドでcanvasを描画します。 また、beforeprint eventを使って、再生中のシーンが描画されるようにします。
window.addEventListener('beforeprint', drawCanvas); function drawCanvas(){ let video = document.getElementById("v"); let canvas = document.getElementById("c"); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext("2d").drawImage(video, 0, 0, video.videoWidth, video.videoHeight); }
表示の切り替え
メディアクエリを使って画面(screen)と印刷(print)の表示を切り替えます。 CSSの@mediaルールを使うとシンプルに実装できます。
@media screen { video { display: block; } canvas { display: none; } } @media print { video { display: none; } canvas { display: block; } }
試してみる
Firefox
ブラウザでの表示:
印刷時の表示:
印刷した瞬間のシーンが表示できました。
Chrome
ブラウザでの表示:
印刷時の表示:
印刷した瞬間のシーンが表示できました。
終わりに
無事、印刷時にvideo要素の表示を再現することが出来ました。 ブラウザでwebページを印刷したときの表示は、配置の調整はあるものの大体そのままという先入観があったので、今回は勉強になりました。
最終的に作成したコードは下記のとおりです。
<!DOCTYPE html> <html> <head> <style> @media screen { video { display: block; } canvas { display: none; } } @media print { video { display: none; } canvas { display: block; } } </style> <script type="text/javascript"> window.addEventListener('beforeprint', drawCanvas); function drawCanvas(){ let video = document.getElementById("v"); let canvas = document.getElementById("c"); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext("2d").drawImage(video, 0, 0, video.videoWidth, video.videoHeight); } </script> </head> <body> <video controls id="v"> <source src="v.mp4" type="video/mp4"> </video> <canvas id="c"></canvas> </body> </html>
本記事の作成にあたって、下記ページを参考にさせていただきました。