#javascript #html #canvas #html5_canvas
Есть довольно интересный вопрос: как я могу захватить конкретный момент видео (с помощью скриншота самого момента конечно) и нарисовать его прямо в не создавая отдельное изображение (которе и содержит этот скриншот) в той же папке? Цель: Есть окно preview в блоке .preview-section который при ховере показывает таймкод того момента, по которому я вожу мышкой. Так вот мне надо захватить этот момент видео и нарисовать его в canvas. PS. Нужно решение без jQuery. Предупреждение: код ну ооочень длинный, так что извините за ваши глаза: var vid, playPauseButton, seekSlider, currentTime, vidDuration, muteButton, volumeSlider, fullScreenToggler, loop, fullscreenHider; var mainVideo, timeCodeContainer, frameContainer, previewBox; function intializePlayer(){ "use strict"; // Set object references vid = document.getElementById("vid"); mainVideo = document.getElementsByClassName('mainVideo')[0]; playPauseButton = document.getElementById("playPauseButton"); seekSlider = document.getElementById("seekSlider"); currentTime = document.getElementById("done"); vidDuration = document.getElementById("duration"); muteButton = document.getElementById("muteUnmute"); volumeSlider = document.getElementById("volumeSlider"); fullScreenToggler = document.getElementById("toggleFullScreen"); loop = document.getElementById("loop"); fullscreenHider = document.getElementById("exitFullScreen"); previewBox = document.getElementsByClassName("preview-section")[0]; timeCodeContainer = document.getElementById("timeCodeContainer"); frameContainer = document.getElementById("frameContainer"); // Add event listeners playPauseButton.addEventListener("click",playPauseVideo,false); seekSlider.addEventListener("input",timeSlider,false); seekSlider.addEventListener("mousemove",sliderHoverValue,false); seekSlider.addEventListener("mouseout",previewBoxFadeOut,false); vid.addEventListener("timeupdate",videoTimeUpdate,false); muteButton.addEventListener("click",muteUnmute,false); volumeSlider.addEventListener("input",volumeChange,false); volumeSlider.addEventListener("input",toggleIcon,false); fullScreenToggler.addEventListener("click",enterFullScreen,false); fullscreenHider.addEventListener("click",exitFullScreen,false); document.addEventListener('webkitfullscreenchange', exitHandler, false); document.addEventListener('mozfullscreenchange', exitHandler, false); document.addEventListener('fullscreenchange', exitHandler, false); document.addEventListener('MSFullscreenChange', exitHandler, false); loop.addEventListener("click",loopVideo,false); //Add some other settings vid.controls = false; vid.oncontextmenu = function(){return false;}; } window.onload = intializePlayer; //Secondary functions function videoFSstyling(video,videoBox){ video.style.width = "100%" video.style.height = "auto"; videoBox.style.width = "100%"; videoBox.style.height = "auto"} function videoNotFSstyling(video,videoBox){ video.removeAttribute("style"); videoBox.removeAttribute("style"); } function fadeIn(el){ el.classList.add('show'); el.classList.remove('hide'); } function fadeOut(el){ el.classList.add('hide'); el.classList.remove('show');} var valueHover = 0; function calcSliderPos(e) { return (e.offsetX / e.target.clientWidth) * parseInt(e.target.getAttribute('max'),10); } //Video Functions function exitHandler(){ "use strict"; if (document.webkitIsFullScreen === false || document.mozFullScreen === false || document.msFullscreenElement === false){ videoNotFSstyling(vid,mainVideo); document.getElementsByClassName("videoControls")[0].classList.remove("fullscreen"); fullscreenHider.style.display = "none"; fullScreenToggler.style.display = "inline-block";} } function playPauseVideo(){ "use strict"; if(vid.paused){ document.title = "►" + " " + document.title; vid.play(); playPauseButton.innerHTML = '';} else { vid.pause(); playPauseButton.innerHTML = '';} } function timeSlider(){ "use strict"; var slideTo = vid.duration * (seekSlider.value / 100); vid.currentTime = slideTo; } function videoTimeUpdate(){ "use strict"; var timeInterval = vid.currentTime * (100 / vid.duration); seekSlider.value = timeInterval; var currentMinutes = Math.floor(vid.currentTime / 60); var currentSeconds = Math.floor(vid.currentTime - currentMinutes * 60); var durationMinutes = Math.floor(vid.duration / 60); var durationSeconds = Math.floor(vid.duration - durationMinutes * 60); if(currentSeconds < 10) {currentSeconds = "0"+ currentSeconds;} if(durationSeconds < 10) {durationSeconds = "0"+ durationSeconds;} if(currentMinutes < 10) {currentMinutes = "0"+ currentMinutes;} if(durationMinutes < 10) {durationMinutes = "0"+ durationMinutes;} currentTime.innerHTML = currentMinutes + ":" + currentSeconds; vidDuration.innerHTML = durationMinutes + ":" + durationSeconds; } function sliderHoverValue(e){ "use strict"; valueHover = Math.round(calcSliderPos(e)); var currentHoverTime = vid.duration * (valueHover / 100); var hoverTimeMinutes, hoverTimeSeconds; currentHoverTime = Math.floor(currentHoverTime); hoverTimeMinutes = Math.floor(currentHoverTime / 60); hoverTimeSeconds = Math.floor(currentHoverTime - hoverTimeMinutes * 60); if(hoverTimeMinutes < 10){hoverTimeMinutes = "0" + hoverTimeMinutes;} if(hoverTimeSeconds < 10){hoverTimeSeconds = "0" + hoverTimeSeconds} timeCodeContainer.innerHTML = hoverTimeMinutes + ":" + hoverTimeSeconds; if(currentHoverTime > Math.floor(vid.duration)){ timeCodeContainer.innerHTML = vidDuration.innerHTML;} if(currentHoverTime < 0){timeCodeContainer.innerHTML = "00:00";} fadeIn(previewBox); var translateXpos = parseFloat(calcSliderPos(e).toFixed(4)); var translateToPosition = ((translateXpos * seekSlider.clientWidth / 100).toFixed(4)); if(translateXpos < 0){ previewBox.setAttribute("style","transform: translate(0%, -106%) !important;"); } else if(translateXpos > seekSlider.clientWidth || parseFloat(translateToPosition) > seekSlider.clientWidth){ previewBox.setAttribute("style","transform: translate(" + seekSlider.clientWidth + "px" + ", -106%) !important;"); } else { previewBox.setAttribute("style","transform: translate(" + translateToPosition + "px" + ", -106%) !important;");} } function previewBoxFadeOut(){fadeOut(previewBox);} function volumeChange(){ "use strict"; vid.volume = volumeSlider.value / 100; } function enterFullScreen(){ "use strict"; if(mainVideo.requestFullScreen){ mainVideo.requestFullScreen(); videoFSstyling(vid,mainVideo);} else if(mainVideo.webkitRequestFullScreen){ mainVideo.webkitRequestFullScreen(); videoFSstyling(vid,mainVideo);} else if(mainVideo.mozRequestFullScreen){ mainVideo.mozRequestFullScreen(); videoFSstyling(vid,mainVideo);} else if(mainVideo.oRequestFullScreen){ mainVideo.oRequestFullScreen(); videoFSstyling(vid,mainVideo);} else if(mainVideo.msRequestFullScreen){ mainVideo.msRequestFullScreen(); videoFSstyling(vid,mainVideo);} document.getElementsByClassName("videoControls")[0].classList.add("fullscreen"); fullScreenToggler.style.display = "none"; fullscreenHider.style.display = "inline-block"; } function exitFullScreen(){ "use strict"; if(document.cancelFullScreen){ document.cancelFullScreen(); videoNotFSstyling(vid,mainVideo);} else if(document.webkitCancelFullScreen){ document.webkitCancelFullScreen(); videoNotFSstyling(vid,mainVideo);} else if(document.mozCancelFullScreen){ document.mozCancelFullScreen(); videoNotFSstyling(vid,mainVideo);} else if(document.oCancelFullScreen){ document.oCancelFullScreen(); videoNotFSstyling(vid,mainVideo);} else if(document.msCancelFullScreenn){ document.msCancelFullScreen(); videoNotFSstyling(vid,mainVideo);} document.getElementsByClassName("videoControls")[0].classList.remove("fullscreen"); fullscreenHider.style.display = "none"; fullScreenToggler.style.display = "inline-block"; } function loopVideo(){ "use strict"; if(!loop.hasAttribute("style")){ loop.setAttribute("style","opacity: 1; color: rgba(22,206,170,1.00);"); vid.setAttribute("loop",""); } else { loop.removeAttribute("style"); vid.removeAttribute("loop"); } } function toggleIcon(){ "use strict"; if(vid.volume <= 0.01){ muteButton.innerHTML = '';} else if(vid.volume <= 0.42){ muteButton.innerHTML = '';} else { muteButton.innerHTML = ''; } } var prev_level; function muteUnmute(){ "use strict"; if(vid.volume >= 0.03){ prev_level = volumeSlider.value; volumeSlider.value = 0; vid.volume = volumeSlider.value; toggleIcon(); } else if(vid.volume <= 0.05){ volumeSlider.value= prev_level; vid.volume = volumeSlider.value / 100; toggleIcon(); } } //KeyPress Fuctions function pressSpaceToStart(e){ "use strict"; if(e.keyCode === 32){ e.preventDefault(); playPauseVideo();} } window.onkeypress = function(o){"use strict"; pressSpaceToStart(o);}; window.onkeydown = function(o){"use strict"; pressSpaceToStart(o);}; button:focus {outline: none !important;} input:focus {outline: none !important;} video::-webkit-media-controls, video::-webkit-media-controls-enclosure {display:none !important;} section.videoSection {width: 100%; margin: auto; margin-top: 30px;} div.mainVideo {text-align: center; width: 454px; margin: auto} div.mainVideo:-webkit-full-screen {background-color: transparent !important;} div.mainVideo video {width: 450px; border: 2px solid black; border-bottom: 0} div.videoControls {width: 450px; margin: -5px auto 0px; background-color: rgba(67,41,82,0.97); padding: 10px 0px 8px 0px; border: 2px solid black; color: snow; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px;} div.videoControls button {background-color: transparent; border: 0; opacity: 0.8;} div.videoControls span {position: relative;} div.videoControls button:hover {opacity: 1;} div.preview-section {position: absolute; width: 100px; height: 70px; transform: translate(0%, -106%); margin-left: -44.5px; opacity: 0;} div.preview-section * {cursor: default;} div.preview-box {position: relative; width: 100px; height: 70px; background-image: linear-gradient(to top, #252323, rgba(0, 0, 0, 0.86)); -webkit-background-image: linear-gradient(to top, #252323, rgba(0, 0, 0, 0.86)); -moz-background-image: linear-gradient(to top, #252323, rgba(0, 0, 0, 0.86)); -o-background-image: linear-gradient(to top, #252323, rgba(0, 0, 0, 0.86)); -ms-background-image: linear-gradient(to top, #252323, rgba(0, 0, 0, 0.86)); border: 1px solid rgba(0,0,0,0.84); box-sizing: border-box; border-bottom: 0; box-shadow: inset 0 0 0 2px #363131; -webkit-box-shadow: inset 0 0 0 2px #363131; -moz-box-shadow: inset 0 0 0 2px #363131; -ms-box-shadow: inset 0 0 0 2px #363131; -o-box-shadow: inset 0 0 0 2px #363131;} div.preview-box #frameContainer {width: 96%; height: 58px; background: #E0E0E0; margin: 1px auto 0px;} div.preview-box #timeCodeContainer {font-size: 0.70em; background-color: rgba(23,22,22,.76); text-align: center; position: absolute; color: white; left: 50%; top: 86%; transform: translate(-50%, -100%); overflow: hidden; display: inline-block; padding: 0px 3px} /* Slider Styling */ input[type=range] {-webkit-appearance: none; margin: 5.8px 0; background-color: transparent !important;} input[type=range]:focus {outline: none;} input[type=range]::-webkit-slider-runnable-track {cursor: pointer; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72); background: #ac62ff; border-radius: 21.6px; border: 1px solid rgba(163, 0, 255, 0.79);} input[type=range]::-webkit-slider-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16, 14, 0.78), 0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77); border-radius: 28px; background: #ffff29; cursor: pointer; -webkit-appearance: none; margin-top: -7.8px;} input[type=range]:focus::-webkit-slider-runnable-track {background: #b16cff;} input[type=range]::-moz-range-track {width: 100%; cursor: pointer; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72); background: #ac62ff; border-radius: 21.6px; border: 1px solid rgba(163, 0, 255, 0.79);} input[type=range]::-moz-range-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16, 14, 0.78), 0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77); border-radius: 28px; background: #ffff29; cursor: pointer;} input[type=range]::-ms-track {width: 100%; cursor: pointer; background: transparent; border-color: transparent; color: transparent;} input[type=range]::-ms-fill-lower {background: #a758ff; border: 1px solid rgba(163, 0, 255, 0.79); border-radius: 43.2px; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72);} input[type=range]::-ms-fill-upper {background: #ac62ff; border: 1px solid rgba(163, 0, 255, 0.79); border-radius: 43.2px; box-shadow: 2.4px 2.4px 6.2px rgba(7, 7, 163, 0.72), 0px 0px 2.4px rgba(8, 8, 187, 0.72);} input[type=range]::-ms-thumb {box-shadow: 2.4px 2.4px 9.5px rgba(4, 16, 14, 0.78), 0px 0px 2.4px rgba(9, 36, 32, 0.78); border: 1.8px solid rgba(0, 0, 6, 0.77); border-radius: 28px; background: #ffff29; cursor: pointer;} input[type=range]:focus::-ms-fill-lower {background: #ac62ff;} input[type=range]:focus::-ms-fill-upper {background: #b16cff;} /* Animationg fadeIn and fadeOut styles */ .show {opacity: 1 !important; transition: opacity 400ms;} .hide {opacity: 0 !important; transition: opacity 400ms;} /* Non fullscreen track and thumb width and height */ /* Track */ .videoControls input[type=range]::-webkit-slider-runnable-track {height: 6.4px;} .videoControls input[type=range]::-moz-range-track {height: 6.4px;} .videoControls input[type=range]::-ms-track {height: 6.4px;} /* Thumb */ .videoControls input[type=range]::-webkit-slider-thumb {height: 20px; width: 8px;} .videoControls input[type=range]::-moz-range-thumb {height: 20px; width: 8px;} .videoControls input[type=range]::-ms-thumb {height: 20px; width: 8px;} /* Video Controls Buttons Styling */ #playPauseButton {float: left; margin: -3px 1px 0px 3px;} #loop {float: left; margin: 4px 5px 25px 3px;} #seekContainer {width: 150px; float: left;} #seekSlider {width: 100%; margin: 10px 5px 0px -1px;} div.mainVideo span {color: snow; font-size: 0.97em; display: inline-block; float: left; margin: 2.5px 0px 0px 1px;} #muteUnmute {margin-top: -5px; float: left;} #volumeSlider {width: 64px; margin: 10px 0px 0px 0px; float: left;} #toggleFullScreen {margin: 0px 0px 0px 4px;} /* Fullscreen settings -START-*/ .fullscreen {z-index: 2789034264 !important; position: absolute !important; width: 80% !important; bottom: 5.7% !important; left: 10% !important; right: 10% !important; height: 35px !important;} .fullscreen button i {font-size: 2.5em !important;} .fullscreen button#playPauseButton {margin-left: 0.2% !important; float: left !important;} .fullscreen #seekContainer {width: 48% !important; margin-left: 2px !important;} .fullscreen button#muteUnmute {margin-left: 0.5%; font-size: 0.98em; margin-top: -10px;} .fullscreen span {font-size: 1.2em !important;} .fullscreen input#volumeSlider {width: 12%; margin-left: 1%;} #exitFullScreen {margin-left: 0.5%; margin-top: -3px;} /* Fullscreen track and thumb width and height */ /* Track */ .fullscreen input[type=range]::-webkit-slider-runnable-track {height: 12.8px;} .fullscreen input[type=range]::-moz-range-track {height: 12.8px;} .fullscreen input[type=range]::-ms-track {height: 12.8px;} /* Thumb */ .fullscreen input[type=range]::-webkit-slider-thumb {height: 32px; width: 12px; margin-top: -10px;} .fullscreen input[type=range]::-moz-range-thumb {height: 32px; width: 12px; margin-top: -10px;} .fullscreen input[type=range]::-ms-thumb {height: 32px; width: 12px; margin-top: -10px;} 00:00 / 00:0000:00
Ответы
Ответ 1
у канвы есть метод drawImage. Погуглите. Вот пример с первой же ссылки function grabScreenshot() { ctx.drawImage(video, 0, 0, videoWidth, videoHeight); var img = new Image(); img.src = canvas.toDataURL("image/png"); img.width = 120; ssContainer.appendChild(img); }Ответ 2
Как вариант: это мотнуть видео на заданное время, сделать скрин и мотнуть обратно. А чтобы всё это дело не видел пользователь, мотайте на клоне video. Но всё это шляпа, по хорошему надо использовать превьюшки в спайте. var $video = $("video"); var $slider = $(".slider"); var $span = $("span"); var $canvas = $("canvas"); var context = $canvas[0].getContext('2d'); $video.on("loadedmetadata", function() { $slider.data("duration", $video[0].duration); console.log($video[0].duration); }); var last_second = 0; var save_second = 0; $slider.on("mousemove", function(e) { var max = $slider.width(); var relX = e.pageX; var time = Math.round($(this).data("duration") * e.pageX / max); if(time != last_second) { last_second = time; console.log(Math.round(relX / max * 100)); $span.css("left", Math.round(relX / max * 100) + "%"); $video[0].currentTime = time; setTimeout(function() { context.drawImage($video[0], 0, 0, 150, 100); }, 300); } }).hover(function() {}, function() { var max = $slider.width(); $video[0].currentTime = save_second; var dur_per = save_second * 100 / $(this).data("duration"); var width = dur_per * max; console.log(width); $span.css("left", width + "%"); }); .slider { position: absolute; height: 50px; background: blue; top:0; left:0; width: 100%; } span { position: absolute; width: 20px; height: 20px; background: red; top: 15px; } canvas { background: black; width: 150px; min-height: 100px; margin-top: 30px; display: none; border: 1px black solid; } .slider:hover canvas { display: block; }
Комментариев нет:
Отправить комментарий