Skip to content

Instantly share code, notes, and snippets.

@tvst
Created December 3, 2019 01:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tvst/c114620cf36b77732d5d67f411c55f12 to your computer and use it in GitHub Desktop.
Save tvst/c114620cf36b77732d5d67f411c55f12 to your computer and use it in GitHub Desktop.
<html>
<head>
<title>Crappy Demo</title>
<script src="ScreenCastRecorder.js"></script>
</head>
<body>
<div>
<button id="startBtn">start</button>
<button id="stopBtn">stop</button>
</div>
<div id="countdown"></div>
<div id="results" style="display: none">
<div>
<a href="javascript:openInTab()" id="viewLink">Open in a tab</a>
|
<a href="#" id="downloadLink">Download</a>
</div>
<video id="videoEl" controls></video>
</div>
<script>
const rec = new ScreenCastRecorder({ recordAudio: true })
const videoEl = document.getElementById("videoEl")
let outUrl;
document.getElementById("startBtn").onclick = () => {
rec.initialize().then(() => countDown())
}
document.getElementById("stopBtn").onclick = async () => {
const blob = await rec.stop()
outUrl = window.URL.createObjectURL(blob)
const download = document.getElementById("downloadLink")
download.href = outUrl
download.download = "test.mp4" // mp4 instead of webm. Makes it playable on Mac.
const countEl = document.getElementById("countdown")
countEl.innerText = "Done!"
showVideo()
document.getElementById("results").style.display = ""
}
function countDown() {
const countEl = document.getElementById("countdown")
let count = 3
const run = () => {
if (count == 0) {
countEl.innerText = "Recording!"
rec.start()
return
}
countEl.innerText = count
count--
window.setTimeout(run, 1000)
}
run()
}
function openInTab() {
window.open(outUrl, "_blank")
}
function showVideo() {
const mediaSource = rec.buildOutputBlob()
videoEl.src = URL.createObjectURL(mediaSource)
videoEl.width = 500
// TODO: when not needed anymore, call URL.revokeObjectURL(videoEl.src)
}
</script>
</body>
</html>
const MEDIA_TYPE = "video/webm;codecs=vp9,opus"
//const MEDIA_TYPE = "video/webm;codecs=h264"
const BLOB_TYPE = "video/webm"
class ScreenCastRecorder {
constructor({ recordAudio }) {
this.recordAudio = recordAudio
this.inputStream = null
this.recordedChunks = []
this.mediaRecorder = null
}
async initialize() {
const desktopStream = await navigator.mediaDevices.getDisplayMedia(
{ video: true })
let tracks = desktopStream.getTracks()
if (this.recordAudio) {
const voiceStream = await navigator.mediaDevices.getUserMedia(
{ video: false, audio: true })
tracks = tracks.concat(voiceStream.getAudioTracks())
}
this.recordedChunks = []
this.inputStream = new MediaStream(tracks)
this.mediaRecorder = new MediaRecorder(this.inputStream, { mimeType: MEDIA_TYPE})
this.mediaRecorder.ondataavailable = (e) => this.recordedChunks.push(e.data)
}
start() {
this.mediaRecorder.start()
}
stop() {
let resolver
const promise = new Promise((r) => {
resolver = r
})
this.mediaRecorder.onstop = () => resolver()
this.mediaRecorder.stop()
this.inputStream.getTracks().forEach(s => s.stop())
this.inputStream = null
return promise.then(() => this.buildOutputBlob())
}
buildOutputBlob() {
return new Blob(this.recordedChunks, {type: BLOB_TYPE})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment