forked from w3c/webcodecs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shows capture from camera, compress and store to a webm file.
- Loading branch information
1 parent
95090a9
commit 913c854
Showing
3 changed files
with
1,299 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="origin-trial" content="AkLPETKVnJC/njTvpbWOu+cyUhX9kjAvSZOOHgrfmlgn7CGKsW0+pVCbEScZU7y90ogjl93LQ4vH4xE2u5t65wgAAAB3eyJvcmlnaW4iOiJodHRwczovL3dlYmNvZGVjcy1ibG9ncG9zdC1kZW1vLmdsaXRjaC5tZTo0NDMiLCJmZWF0dXJlIjoiV2ViQ29kZWNzIiwiZXhwaXJ5IjoxNjE1MjMzMTk4LCJpc1N1YmRvbWFpbiI6dHJ1ZX0="> | ||
<title>WebCodecs API demo: Encoding and Decoding</title> | ||
<style> | ||
button { | ||
background-color: #555555; | ||
border: 2px; | ||
border-radius: 2px; | ||
color: white; | ||
padding: 15px 32px; | ||
width: 1280px; | ||
text-align: center; | ||
display: block; | ||
font-size: 16px; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<button id="record" width=1280 onclick="saveFile()">Record</button> | ||
<video id ="src" autoplay muted width=1280 height=720></video> | ||
<script type="text/javascript" src="webm-writer2.js"></script> | ||
<script> | ||
var writeable; | ||
var videoWriter; | ||
var stop = false; | ||
let codec_string = "vp09.00.10.08"; | ||
var video; | ||
var stream; | ||
|
||
async function saveFile() { | ||
let cnv = document.getElementById("src"); | ||
let btn = document.getElementById('record'); | ||
if (btn.innerText == "Stop") { | ||
stop = true; | ||
await videoWriter.complete(); | ||
writeable.close(); | ||
btn.innerText = "Record"; | ||
return ; | ||
} | ||
let width = cnv.width; | ||
let height = cnv.height; | ||
stop = false; | ||
handle = await window.showSaveFilePicker({ | ||
startIn: 'videos', | ||
suggestedName: "myVideo.webm", | ||
types: [{ | ||
description: 'Video File', | ||
accept: {'video/webm' :['.webm']} | ||
}], | ||
}); | ||
|
||
writeable = await handle.createWritable(); | ||
videoWriter = new WebMWriter({ | ||
fileWriter: writeable, | ||
codec: (codec_string=='vp8'?'VP8':'VP9'), | ||
width: width, | ||
height: height | ||
}); | ||
captureAndEncode((chunk) => { | ||
videoWriter.addFrame(chunk); | ||
}); | ||
document.getElementById('record').innerText = "Stop"; | ||
}; | ||
|
||
async function captureAndEncode(processChunk) { | ||
let frame_counter = 0; | ||
var track = stream.getTracks()[0]; | ||
var settings = track.getSettings(); | ||
var pending_outputs = 0; | ||
var prc = new MediaStreamTrackProcessor(track); | ||
var frameStream = prc.readable; | ||
const frameReader= frameStream.getReader(); | ||
|
||
const init = { | ||
output: (chunk) => { | ||
pending_outputs--; | ||
processChunk(chunk); | ||
}, | ||
error: (e) => { | ||
console.log(e.message); | ||
vtr.stop(); | ||
} | ||
}; | ||
|
||
const config = { | ||
codec: codec_string, | ||
width: settings.width, | ||
height: settings.height, | ||
bitrate: 10e6, | ||
}; | ||
|
||
let encoder = new VideoEncoder(init); | ||
encoder.configure(config); | ||
frameReader.read().then(function processFrame({done, value}) { | ||
|
||
if(done) { | ||
self.postMessage("Stream is done."); | ||
value.close(); | ||
frameReader.releaseLock(); | ||
return; | ||
} | ||
|
||
if (!stop && pending_outputs <= 30) { | ||
if (++frame_counter % 20 == 0) { | ||
console.log(frame_counter); | ||
} | ||
|
||
pending_outputs++; | ||
const insert_keyframe = (frame_counter % 150) == 0; | ||
encoder.encode(value, { keyFrame: insert_keyframe }); | ||
} | ||
value.close(); | ||
frameReader.read().then(processFrame); | ||
}); | ||
} | ||
async function main() { | ||
video = document.getElementById("src"); | ||
let constraints = { audio: false, video: { width: 1280, height: 720, frameRate: 30 } }; | ||
stream = await window.navigator.mediaDevices.getUserMedia(constraints); | ||
video.srcObject = stream; | ||
} | ||
|
||
document.body.onload = main; | ||
</script> | ||
|
||
</body> | ||
|
||
</html> | ||
|
Oops, something went wrong.