Now you can select input devices

This commit is contained in:
Neale Pickett 2020-03-08 12:03:22 -06:00
parent 1fe0b35757
commit 0cc7fcb945
3 changed files with 117 additions and 29 deletions

View File

@ -35,8 +35,7 @@ class Convulse {
document.querySelector("canvas").addEventListener("click", e => this.rec(e))
document.querySelector("#rec").addEventListener("click", e => this.rec(e))
//document.querySelector("#save").addEventListener("click", e => this.save(e))
document.querySelector("#webcam-size").addEventListener("input", e => this.setWebcamSize(e))
document.querySelector("#webcam-size").value = localStorage.webcamSize || 0.3
document.querySelector("#webcam-size").dispatchEvent(new Event("input"))
@ -51,19 +50,34 @@ class Convulse {
this.recorder = {state: "unstarted"}
// this.mediaStream gets audio directly from the device, video from canvas
this.mediaStream = new MediaStream()
navigator.mediaDevices.getUserMedia({video: true, audio: true})
.then(media => {
document.querySelector("#hello").classList.add("hidden")
this.webcamVideo.muted = true
this.webcamVideo.srcObject = media
this.webcamVideo.play()
for (let at of media.getAudioTracks()) {
this.mediaStream.addTrack(at)
console.log("Adding audio track", at)
// Populate select boxes with what media is available
navigator.mediaDevices.enumerateDevices()
.then(devs => {
for (let dev of devs) {
let opt = document.createElement("option")
opt.value = dev.deviceId
if (dev.kind == "audioinput") {
opt.text = dev.label || `Microphone ${aud.length+1}`
aud.appendChild(opt)
} else if (dev.kind == "videoinput") {
opt.text = dev.label || `Camera ${vid.length+1}`
vid.appendChild(opt)
}
}
})
// Pretend the user clicked whatever's in those boxes
let aud = document.querySelector("#audio-in")
let vid = document.querySelector("#video-in")
aud.addEventListener("change", e => this.inputSelect(e))
vid.addEventListener("change", e => this.inputSelect(e))
this.inputSelect()
navigator.mediaDevices.getUserMedia({video: true, audio: true})
.then(media => this.gotUserMedia(media))
.catch(err => {
toast("Couldn't open camera!")
})
@ -81,7 +95,6 @@ class Convulse {
let canvasStream = this.canvas.captureStream(30)
for (let vt of canvasStream.getVideoTracks()) {
this.mediaStream.addTrack(vt)
console.log("Adding video track", vt)
}
this.frame()
@ -89,6 +102,52 @@ class Convulse {
toast("Click anywhere to start and stop recording")
}
gotUserMedia(media) {
document.querySelector("#hello").classList.add("hidden")
// Set video source
// sending this to an HTML element seems janky, is there no direct method for video?
if (this.webcamVideo.srcObject) {
for (let track of this.webcamVideo.srcObject.getTracks()) {
track.stop()
}
}
for (let track of media.getVideoTracks()) {
for (let opt of document.querySelector("#video-in")) {
if (opt.text == track.label) {
opt.selected = true
}
}
}
this.webcamVideo.muted = true
this.webcamVideo.srcObject = media
this.webcamVideo.play()
// Set audio source
for (let track of this.mediaStream.getAudioTracks()) {
this.mediaStream.removeTrack(track)
track.stop()
}
for (let track of media.getAudioTracks()) {
this.mediaStream.addTrack(track)
for (let opt of document.querySelector("#audio-in")) {
opt.selected = (opt.value == track.deviceId)
}
}
}
inputSelect(event) {
let audName = document.querySelector("#audio-in").value || undefined
let vidName = document.querySelector("#video-in").value || undefined
let constraints = {
audio: {deviceId: {exact: audName}},
video: {deviceId: {exact: vidName}}
}
navigator.mediaDevices.getUserMedia(constraints)
.then(e => this.gotUserMedia(e))
}
setWebcamSize(event) {
this.webcamSize = event.target.value
localStorage.webcamSize = this.webcamSize

View File

@ -38,6 +38,10 @@
<button id="rec">⏺️</button>
<a id="save">💾</a>
</div>
<div>
<span>🎙️<select id="audio-in"></select></span>
<span>🎥<select id="video-in"></select></span>
</div>
<div id="webcam-controls">
UR FACE
<input id="webcam-size" type="range" min="0" max="1" step="0.01" value="0.2">

View File

@ -1,26 +1,51 @@
var cacheName = "convulse-v1";
// jshint asi:true
var cacheName = "v2";
var content = [
"index.html",
"convulse.css",
"convulse.js",
"convulse.png"
];
]
self.addEventListener("install", e => {
e.waitUntil(caches.Open(cacheName).then(cache => cache.addAll(content)));
});
self.addEventListener("install", preCache)
self.addEventListener("fetch", cachingFetch)
self.addEventListener("activate", handleActivate)
// Have mercy, this is a horror show
self.addEventListener("fetch", e => {
e.respondWith(
caches.match(e.request).then(r => {
return r || fetch(e.request).then(response => {
return caches.open(cacheName).then(cache => {
cache.put(e.request, response.clone());
return response;
});
});
function handleActivate(event){
event.waitUntil(
cleanup()
)
}
async function cleanup(event) {
let cacheNames = await caches.keys()
for (let name of cacheNames) {
if (name != cacheName) {
console.log("Deleting old cache", name)
caches.delete(name)
}
}
}
function preCache(event) {
event.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll(content))
)
}
// Go try to pull a newer version from the network,
// but return what's in the cache for this request
function cachingFetch(event) {
fetch(event.request)
.then(resp => {
caches.open(cacheName)
.then(cache => {
cache.put(event.request, resp.clone())
})
);
});
})
event.respondWith(caches.match(event.request))
}