#author("2020-02-02T17:41:53+09:00;2019-12-25T13:28:47+09:00","default:inoue.ko","inoue.ko") #author("2026-07-28T16:00:40+09:00;2026-07-28T13:58:42+09:00","default:inoue.ko","inoue.ko") *JavaScript| Video ~ //RIGHT: //[[WebDesign/JavaScript]] //#clear HTML + CSS + JavaScriptによるページのサンプルソースを紹介しています。 HTML5で実装された<VIDEO>と<CANVAS>を利用しています。 ~ ***はじめに VIDEO要素の再生、一時停止、はじめに戻す・・といった操作はAUDIO要素の場合と同様にJavaScript を通じて制御可能です。> 参考:[[JavaScript/Audio]] -video要素.play(); 再生 -video要素.pause(); 一時停止 -video要素.currentTime = 0; 頭出し -video要素.volume += 0.25; 音量の制御 などなど ~ 例えば、以下のようなコードがあると、動画の再生を制御できます。 var v = document.getElementsByTagName("video")[0]; v.play(); ~ ***事例1 VIDEO → CANVAS [[→DEMO>https://design.kyusan-u.ac.jp/SampleSite/JS_VideoToCanvas01/]] ***事例1 VIDEO → CANVAS [[→DEMO>https://design.cs.kyusan-u.ac.jp/SampleSite/JS_VideoToCanvas01/]] [draw]を押すと、 VIDEOタグで配置された動画が、タイマーを使ってCANVASへ転送されます。単にVIDEOの内容をCANVASデバイスにdrawImage関数で描き続けているだけなので、同じものが並んで見えます。 後のサンプルの前段となる基礎の確認です。 ~ ''index.html'' | ページの文書構造 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Basic Sample</title> <script type="text/javascript" src="sample.js"></script> <link rel="stylesheet" type="text/css" href="sample.css"> </head> <body> <video id="myVideo" width="480" height="360" src="sample.webm" autoplay loop></video> <canvas id="myCanvas" width="480" height="360"></canvas> <button id="myButton" onclick="start()">draw</button> </body> </html> ~ ''sample.css'' | ページのビジュアル 省略 ~ ''sample.js'' | ページのふるまい function start(){ var myTimer = setInterval(Draw,1000/30); } function Draw(){ var cnvs = document.getElementById("myCanvas"); var dc = cnvs.getContext("2d"); dc.drawImage(myVideo,0,0,480,360); } ~ 参考:drawImage関数の書き方 dc.drawImage(cnvs, x, y) dc.drawImage(cnvs, x, y, width, height) ここで、dcは2次元の[[デバイスコンテキスト>Google:JavaScript canvas デバイスコンテキスト]]を意味します。 ~ ~ ***事例2 フィルタリング [[→DEMO>https://design.kyusan-u.ac.jp/SampleSite/JS_VideoToCanvas02/]] ***事例2 フィルタリング [[→DEMO>https://design.cs.kyusan-u.ac.jp/SampleSite/JS_VideoToCanvas02/]] 事例1をそのまま応用しています。VIDEOからCANVASへの転送の際、ピクセル単位に色値を計算してモノクロにフィルタリングしています。 ''index.html'' | ページの文書構造 省略:事例1と同じです。 ~ ''sample.css'' | ページのビジュアル 省略 ~ ''sample.js'' | ページのふるまい function start(){ var myTimer = setInterval(Draw,1000/30); } function Draw(){ var cnvs = document.getElementById("myCanvas"); var dc = cnvs.getContext("2d"); dc.drawImage(myVideo,0,0,480,360); var pxData = dc.getImageData(0,0,480,360); for(var y=0; y<360; y++){ for(var x=0; x<480; x++){ var i = ( y*480 + x ) * 4; var m = 0.299*pxData.data[i] +0.587*pxData.data[i+1] +0.114*pxData.data[i+2]; pxData.data[i] = pxData.data[i+1] = pxData.data[i+2] = Math.floor(m); pxData.data[i+3] = 255; //α値 } } dc.putImageData(pxData,0,0); } -参考1:画素の色値の格納 画像データは、配列 pxData.data[0]から順に、R,G,B,αの4つが並んで記録されています。以下の4つで最初の1ピクセル分です。 pxData.data[0] :R値 0 -255 pxData.data[1] :G値 0 -255 pxData.data[2] :B値 0 -255 pxData.data[3] :α値 0 -255 よって、例えば 480*360 の画像の場合 480*360*4 個の配列要素を持ちます。 -参考2:モノクロ化(画像の輝度) RGBを足して3で割る・・という単純計算ではなく、通常はRGBからYUVに変換して、そのうちの輝度成分である Yについて取り出します。一般には以下のように各色値に重み付けをします。 Y = 0.299 R + 0.587 G + 0.114 B ~ ~ ***事例3 Drop Video [[→DEMO>https://design.kyusan-u.ac.jp/SampleSite/JS_VideoDrop/]] ***事例3 Drop Video [[→DEMO>https://design.cs.kyusan-u.ac.jp/SampleSite/JS_VideoDrop/]] ページ上に置かれたVIDEO要素に、手元の動画ファイルをドロップして表示するサンプルです。FileAPIを使います。 ''index.html'' | ページの文書構造 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>Basic Sample</title> <script type="text/javascript" src="sample.js"></script> <link rel="stylesheet" type="text/css" href="sample.css"> </head> <body> <video autoplay loop controls poster="DropFilesHere.png"></video> <video autoplay loop controls poster="DropFilesHere.png"></video> <video autoplay loop controls poster="DropFilesHere.png"></video> <video autoplay loop controls poster="DropFilesHere.png"></video> <p id="progress"></p> </body> </html> ~ ''sample.css'' 要点のみ| ページのビジュアル video { float: left; margin: 40px; width: 360px; height: 240px; object-fit: cover; background-color: silver; } 以下省略 ~ ''sample.js'' | ページのふるまい window.onload =function(){ var vobj = document.getElementsByTagName("video"); for( i=0; i<vobj.length; i++){ vobj[i].addEventListener("dragover", DragoverEvent, false); vobj[i].addEventListener("drop", DropEvent, false); } } function DragoverEvent(ev){ ev.preventDefault(); } function DropEvent(ev){ ev.preventDefault(); DropVideo(ev); } function DropVideo(ev){ var targetObj = ev.currentTarget; var file = ev.dataTransfer.files[0]; var fileType = file.name.slice(-4).toLowerCase(); if( fileType == "webm" || fileType == ".ogv" || fileType == ".mp4" ){ var reader = new FileReader(); reader.readAsDataURL(file); reader.onprogress = function(ev){ if( ev.lengthComputable == true && ev.total > 0 ) { var rate =( ev.loaded *100 / ev.total ).toFixed(1); document.getElementById('progress').innerHTML = "Now Loading .. " + rate + "%"; } } reader.onloadend = function(){ document.getElementById('progress').innerHTML = ""; targetObj.setAttribute("src",reader.result); } }else{ alert("File available only WebM, ogv, mp4"); } } ~ ~