Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

Add searchable select for choosing camera #39

Merged
merged 1 commit into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"react-paginate": "^6.3.2",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.3",
"react-select": "^2.0.0-beta.7",
"react-webcam": "^5.2.0"
},
"scripts": {
Expand Down
7 changes: 5 additions & 2 deletions client/src/components/WebcamCapture.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const WebcamStreamCapture = ({
onCaptureReady,
onError,
onStopCapture,
cameraInput,
}) => {
const webcamRef = useRef(null)
const mediaRecorderRef = useRef(null)
Expand Down Expand Up @@ -61,7 +62,6 @@ const WebcamStreamCapture = ({

const prepareMediaRecorder = async () => {
const constraints = getConstraints()

stream = await navigator.mediaDevices.getUserMedia(constraints)
mediaRecorderRef.current = new MediaRecorder(webcamRef.current.stream, {
mimeType: 'video/webm',
Expand Down Expand Up @@ -90,7 +90,10 @@ const WebcamStreamCapture = ({

return (
<Webcam
videoConstraints={{ aspectRatio: getAspectRatio() }}
videoConstraints={{
aspectRatio: getAspectRatio(),
deviceId: cameraInput.value.deviceId,
}}
className={className}
audio={false}
ref={webcamRef}
Expand Down
Binary file added client/src/no_camera.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 51 additions & 7 deletions client/src/pages/Create/Create.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React, { useState, useCallback } from 'react'
import download from 'downloadjs'
import { Link } from 'react-router-dom'
import './Create.css'
import AsyncSelect from 'react-select/lib/Async'
import Webcam from '../../components/WebcamCapture'
import Countdown from '../../components/Countdown'
import Page from '../../components/Page'
import Icon from '../../components/Icon'
import Button from '../../components/Button'
import GenericWarning from './GenericWarning'
import BrowserWarning from './BrowserWarning'
import noCameraImgSrc from '../../no_camera.png'

const WARNING_BROWSER = 'warning_browser'
const WARNING_GENERIC = 'warning_generic'
Expand All @@ -21,6 +23,7 @@ const PHASE_END = 'phase_end'

function Create({ history }) {
const [phase, setPhase] = useState(PHASE_START)
const [recodingInput, setRecordingInput] = useState(null)
const [isWebcamReady, setIsWebcamReady] = useState(false)
const [gifId, setGifId] = useState()
const [text, setText] = useState('')
Expand All @@ -30,6 +33,28 @@ function Create({ history }) {
window.MediaRecorder ? false : WARNING_BROWSER,
)

const cameraOptions = () =>
navigator.mediaDevices
.enumerateDevices()
.then((inputs) => {
const options = []
inputs
.filter((input) => {
return input.kind === 'videoinput'
})
.forEach((videoInput) => {
options.push({
value: videoInput,
label: videoInput.label,
})
})
return options
})
.catch((err) => {
console.error('ERROR: No camera input found', err)
return []
})

const retry = () => {
setGifId(null)
setText('')
Expand Down Expand Up @@ -127,6 +152,19 @@ function Create({ history }) {
[WARNING_GENERIC]: <GenericWarning retry={retry} />,
[WARNING_BROWSER]: <BrowserWarning />,
}
const webCamCompo = recodingInput ? (
<Webcam
className="gif-video"
onError={() => setWarning(WARNING_GENERIC)}
onCaptureReady={() => setIsWebcamReady(true)}
recordingInput={recodingInput}
onStopCapture={onStopCapture}
isPlaying={phase === PHASE_RECORDING}
cameraInput={recodingInput}
/>
) : (
<img className="gif-video" src={noCameraImgSrc} alt="" />
)

return (
<Page
Expand All @@ -146,15 +184,21 @@ function Create({ history }) {
alt="Your GIF"
/>
) : (
<Webcam
className="gif-video"
onError={() => setWarning(WARNING_GENERIC)}
onCaptureReady={() => setIsWebcamReady(true)}
onStopCapture={onStopCapture}
isPlaying={phase === PHASE_RECORDING}
/>
webCamCompo
)}
</div>
<div className="container">
<AsyncSelect
cacheOptions
defaultOptions
placeholder="Select your camera..."
onChange={setRecordingInput}
noOptionsMessage={() => {
return 'No camera detected...'
}}
loadOptions={cameraOptions}
/>
</div>
{isPrerecordingPhase && (
<Countdown
isPlaying={phase === PHASE_COUNTDOWN}
Expand Down
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.