16/09/2023
I en verden, hvor webapplikationer bliver stadig mere interaktive og funktionsrige, er adgang til enhedens hardware en game-changer. Forestil dig at kunne foretage videoopkald direkte i browseren, tage billeder eller endda oprette unikke augmented reality-oplevelser. Alt dette er muligt takket være HTML5 og dets avancerede API'er, især MediaDevices API. Denne omfattende guide vil dykke ned i, hvordan du kan udnytte kraften i din enheds front-vendte kamera ved hjælp af HTML5 og JavaScript, og give dig en dybdegående forståelse af processen.

- Introduktion til MediaDevices API
- Forudsætninger
- Trin 1: Kontrol af Enhedens Understøttelse
- Trin 2: Anmodning om Brugerens Tilladelse
- Trin 3: Forståelse af Mediebegrænsninger (Constraints)
- Trin 4: Brug af enumerateDevices Metoden
- Trin 5: Visning af Videostrømmen i Browseren
- Struktur af en Kamera-app
- Konklusion
- Ofte Stillede Spørgsmål (FAQ)
Introduktion til MediaDevices API
Med introduktionen af HTML5 blev der åbnet op for nye muligheder ved at give adgang til enhedens hardware via forskellige API'er. Blandt disse står MediaDevices API som en central komponent, der muliggør adgang til medieinputenheder som lyd og video. Denne API er designet til at give udviklere mulighed for at streame og vise live videofeed direkte i browseren. Ved hjælp af getUserMedia-metoden kan du få adgang til videostrømmen fra brugerens enhed og vise den.
getUserMedia-metoden er kernen i denne funktionalitet. Den arbejder ved at producere en MediaStream, som indeholder de anmodede medietyper, hvad enten det er lyd eller video. Den resulterende stream kan derefter bruges til at vise videofeed i browseren, hvilket er essentielt for realtids kommunikation. Når den kombineres med MediaStream Recording API, åbner der sig yderligere muligheder for at optage og gemme mediedata fanget i browseren. Det er vigtigt at bemærke, at denne API, ligesom andre nyere API'er, kun fungerer på sikre oprindelser (HTTPS), men den understøtter også localhost og fil-URL'er for udviklingsformål.
Forudsætninger
For at følge denne guide succesfuldt, er en grundlæggende forståelse af JavaScript essentiel. Hvis du er ny inden for JavaScript, kan det være en god idé at gennemgå ressourcer om grundlæggende JavaScript-programmering. Denne tutorial vil forklare koncepterne og demonstrere eksempler, der kan testes direkte i din browser eller via platforme som CodePen.
Trin 1: Kontrol af Enhedens Understøttelse
Det første skridt er at verificere, om brugerens browser understøtter MediaDevices API. Denne API er en del af navigator-interfacet, som indeholder den aktuelle tilstand og identitet for brugeragenten. Du kan udføre denne kontrol med følgende JavaScript-kode:
if ( 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices ) { console.log( "Let's get this party started" ); }Denne kode tjekker først, om mediaDevices API'en eksisterer inden for navigator, og derefter, om getUserMedia-metoden er tilgængelig inden for mediaDevices. Hvis begge betingelser er sande, er din browser klar til at gå videre.
Trin 2: Anmodning om Brugerens Tilladelse
Efter at have bekræftet browserens understøttelse af getUserMedia, er det næste skridt at anmode om brugerens tilladelse til at bruge enhedens medieinputenheder. Typisk returnerer denne anmodning et Promise, der, når det godkendes af brugeren, opløses til en medietrøm. Hvis brugeren nægter adgang, returneres Promise'en ikke, og adgangen til enhederne blokeres.
Du kan anmode om tilladelse med følgende linje:
navigator.mediaDevices.getUserMedia( { video: true } );Objektet, der sendes som argument til getUserMedia-metoden, kaldes constraints. Dette objekt specificerer, hvilke medietyper du anmoder om adgang til. For eksempel, hvis objektet indeholder audio: true, vil brugeren blive bedt om tilladelse til at få adgang til lydinputenheden.
Trin 3: Forståelse af Mediebegrænsninger (Constraints)
Constraints-objektet er et MediaStreamConstraints-objekt, der specificerer typerne af medier, der skal anmodes om, samt kravene for hver medietype. Du kan definere specifikke krav til den anmodede stream, såsom opløsningen på videostrømmen eller om du ønsker at bruge det front- eller bagvendte kamera. Det er obligatorisk at specificere enten audio eller video, når du foretager en anmodning. Hvis de anmodede medietyper ikke findes på brugerens browser, returneres en NotFoundError.
Video Opløsningsindstillinger
Du kan specificere ønskede opløsninger:
{ video: { width: 1280, height: 720 } }Browseren vil forsøge at matche disse indstillinger. Hvis enheden ikke kan levere den specificerede opløsning, returneres en af de tilgængelige opløsninger.
For at sikre en minimumsopløsning, kan du bruge min-egenskaben:
{ video: { width: { min: 1280 }, height: { min: 720 } } }Dette garanterer, at stream-opløsningen er mindst 1280x720. Hvis dette minimumskrav ikke kan opfyldes, vil Promise'en blive afvist med en OverconstrainedError.
For at spare data og begrænse opløsningen, kan du bruge max-egenskaben:
{ video: { width: { min: 1280, max: 1920 }, height: { min: 720, max: 1080 } } }Disse indstillinger sikrer, at streamen ikke er lavere end 1280x720 og ikke højere end 1920x1080.
Andre nyttige egenskaber inkluderer exact og ideal. ideal bruges ofte sammen med min og max for at finde den bedst mulige indstilling tættest på de ideelle værdier:
{ video: { width: { min: 1280, ideal: 1920, max: 2560 }, height: { min: 720, ideal: 1080, max: 1440 } } }Valg af Kamera: Front- eller Bagvendt
For at specificere, hvilket kamera der skal bruges (f.eks. det front-vendte på mobile enheder), kan du tilføje egenskaben facingMode til videoobjektet:
{ video: { width: { min: 1280, ideal: 1920, max: 2560 }, height: { min: 720, ideal: 1080, max: 1440 }, facingMode: 'user' } }Indstillingen 'user' vil altid forsøge at bruge det front-vendte kamera. For at bruge det bagvendte kamera på mobile enheder kan du ændre facingMode til 'environment':
{ video: { ... // Andre indstillinger facingMode: { exact: 'environment' } } }Brug af exact sikrer, at browseren kun vælger den angivne kameratype, hvis den er tilgængelig.

Trin 4: Brug af enumerateDevices Metoden
enumerateDevices-metoden returnerer en liste over alle tilgængelige input medieenheder på brugerens computer. Dette er utroligt nyttigt, hvis du ønsker at give brugeren mulighed for at vælge, hvilken specifik enhed der skal bruges til lyd- eller videostreaming. Metoden returnerer et Promise, der opløses til et MediaDeviceInfo-array, som indeholder information om hver enhed.
Her er et eksempel på, hvordan metoden bruges:
async function getDevices() { const devices = await navigator.mediaDevices.enumerateDevices(); }Et eksempel på et svar for en enhed kunne se således ud:
{ deviceId: "23e77f76e308d9b56cad920fe36883f30239491b8952ae36603c650fd5d8fbgj", groupId: "e0be8445bd846722962662d91c9eb04ia624aa42c2ca7c8e876187d1db3a3875", kind: "audiooutput", label: "" }Bemærk: En label vil kun blive returneret, hvis der er en tilgængelig stream, eller hvis brugeren har givet tilladelse til enhedsadgang.
Trin 5: Visning af Videostrømmen i Browseren
Efter at have anmodet om og fået adgang til medieenhederne, konfigureret begrænsningerne for opløsning og valgt det ønskede kamera, er det tid til at se resultatet. For at sikre, at streamen leverer baseret på de konfigurerede indstillinger, skal du bruge <video>-elementet. Som nævnt tidligere returnerer getUserMedia-metoden et Promise, der kan opløses til en stream. Denne stream kan konverteres til en objekt-URL ved hjælp af createObjectURL-metoden. Denne URL sættes derefter som videokildemateriale.
Opbygning af en Simpel Kamera-Demo
Lad os nu opbygge en simpel demo, hvor brugeren kan vælge mellem deres tilgængelige videokameraer ved hjælp af enumerateDevices-metoden.
HTML Struktur (index.html)
Opret en index.html-fil med følgende indhold:
Kamera Demo CSS Styling (style.css)
Opret en style.css-fil for at style komponenterne:
.screenshot-image { width: 150px; height: 90px; border-radius: 4px; border: 2px solid whitesmoke; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1); position: absolute; bottom: 5px; left: 10px; background: white; } .display-cover { display: flex; justify-content: center; align-items: center; width: 70%; margin: 5% auto; position: relative; } video { width: 100%; background: rgba(0, 0, 0, 0.2); } .video-options { position: absolute; left: 20px; top: 30px; } .controls { position: absolute; right: 20px; top: 20px; display: flex; } .controls > button { width: 45px; height: 45px; text-align: center; border-radius: 100%; margin: 0 6px; background: transparent; } .controls > button:hover svg { color: white !important; } @media (min-width: 300px) and (max-width: 400px) { .controls { flex-direction: column; } .controls button { margin: 5px 0 !important; } } .controls > button > svg { height: 20px; width: 18px; text-align: center; margin: 0 auto; padding: 0; } .controls button:nth-child(1) { border: 2px solid #D2002E; } .controls button:nth-child(1) svg { color: #D2002E; } .controls button:nth-child(2) { border: 2px solid #008496; } .controls button:nth-child(2) svg { color: #008496; } .controls button:nth-child(3) { border: 2px solid #00B541; } .controls button:nth-child(3) svg { color: #00B541; } JavaScript Funktionalitet (script.js)
Opret en script.js-fil for at tilføje interaktivitet:
feather.replace(); const controls = document.querySelector('.controls'); const cameraOptions = document.querySelector('.video-options>select'); const video = document.querySelector('video'); const canvas = document.querySelector('canvas'); const screenshotImage = document.querySelector('img'); const buttons = [...controls.querySelectorAll('button')]; let streamStarted = false; const [play, pause, screenshot] = buttons; // Grundlæggende constraints for video const constraints = { video: { width: { min: 1280, ideal: 1920, max: 2560 }, height: { min: 720, ideal: 1080, max: 1440 } } }; // Henter og viser tilgængelige kameraindstillinger const getCameraSelection = async () => { const devices = await navigator.mediaDevices.enumerateDevices(); const videoDevices = devices.filter(device => device.kind === 'videoinput'); const options = videoDevices.map(videoDevice => { return <option value="${videoDevice.deviceId}">${videoDevice.label}</option>; }); cameraOptions.innerHTML = options.join(''); }; // Starter videostrømmen play.onclick = () => { if (streamStarted) { video.play(); play.classList.add('d-none'); pause.classList.remove('d-none'); return; } if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) { const updatedConstraints = { ...constraints, deviceId: { exact: cameraOptions.value } }; startStream(updatedConstraints); } }; const startStream = async (constraints) => { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); handleStream(stream); } catch (error) { console.error('Fejl ved start af stream:', error); // Håndter fejl, f.eks. ved at vise en besked til brugeren } }; // Håndterer den modtagne stream const handleStream = (stream) => { video.srcObject = stream; play.classList.add('d-none'); pause.classList.remove('d-none'); screenshot.classList.remove('d-none'); streamStarted = true; }; // Opdaterer streamen, når brugeren vælger et andet kamera cameraOptions.onchange = () => { const updatedConstraints = { ...constraints, deviceId: { exact: cameraOptions.value } }; startStream(updatedConstraints); }; // Pauser videostrømmen const pauseStream = () => { video.pause(); play.classList.remove('d-none'); pause.classList.add('d-none'); }; // Tager et skærmbillede const doScreenshot = () => { canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0); screenshotImage.src = canvas.toDataURL('image/webp'); screenshotImage.classList.remove('d-none'); }; pause.onclick = pauseStream; screenshot.onclick = doScreenshot; // Initialiserer kameraudvælgelse ved indlæsning getCameraSelection(); Struktur af en Kamera-app
En typisk kamera-app, som vi har bygget her, består af flere nøglekomponenter:
- Videoelement: Viser live-feedet fra kameraet.
- Kontrolknapper: Bruges til at starte, pause og tage billeder (f.eks. shutter-knap).
- Kameraudvælgelse: En dropdown-menu, der lader brugeren vælge mellem forskellige tilgængelige kameraer.
- Canvas-element: Bruges til midlertidigt at gemme billeddata fra videostrømmen, før det gemmes som en fil.
- Billedvisning: Viser det senest tagne billede eller et galleri.
MediaStream API er afgørende for at muliggøre disse funktioner. Den giver os mulighed for at få adgang til kameraet, håndtere datastrømmen og behandle billeddata direkte i browseren.
Konklusion
Ved at udnytte HTML5's MediaDevices API og JavaScript kan du nemt integrere kamerafunktionalitet i dine webapplikationer. Fra at anmode om tilladelser til at styre videoopløsninger og vælge specifikke kameraer, giver disse værktøjer dig fuld kontrol. Den demonstrerede demo giver et solidt udgangspunkt for at bygge mere avancerede kamera- og videoapplikationer, såsom videoopkald, streamingtjenester eller kreative fotoapps.
Ofte Stillede Spørgsmål (FAQ)
Hvordan sikrer jeg, at mit websted kan få adgang til kameraet?
Du skal bruge navigator.mediaDevices.getUserMedia() og sikre, at din side serveres via HTTPS eller localhost. Brugeren vil blive bedt om at give tilladelse.
Hvad sker der, hvis brugeren nægter adgang til kameraet?
Hvis brugeren nægter tilladelse, vil getUserMedia() returnere en Promise, der bliver afvist, og din applikation vil ikke kunne få adgang til kameraet. Det er god praksis at informere brugeren om, hvorfor adgang er nødvendig.
Kan jeg bruge både front- og bagvendte kameraer?
Ja, du kan specificere dette ved hjælp af facingMode-egenskaben i constraints-objektet, f.eks. { facingMode: 'user' } for front-vendt og { facingMode: 'environment' } for bagvendt.
Hvad er forskellen mellem ideal og exact i constraints?
ideal angiver en ønsket indstilling, som browseren vil forsøge at matche, men kan afvige fra, hvis det er nødvendigt. exact kræver, at den specificerede indstilling opfyldes præcist, ellers fejler anmodningen.
Hvis du vil læse andre artikler, der ligner Brug kameraet med HTML5: En komplet guide, kan du besøge kategorien Teknologi.
