Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.1.0 #3

Merged
merged 18 commits into from
Jan 29, 2019
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add video stream and download example
timone committed Dec 6, 2018
commit ea712e771b02d82a1e8c8ff4deb528a6b193e5dd
67 changes: 50 additions & 17 deletions camerakit-web/camerakit-web.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import adapter from 'webrtc-adapter';

const handleError = (error) => {
console.log('Error: ', error);
};
console.log(`Using webrtc-adapter ${adapter.extractVersion}`);

let recordedBlobs = [];
let mediaRecorder;
const CameraKitWeb = {
getDevices: async () => {
const audioSources = [];
const videoSources = [];
await navigator.mediaDevices.enumerateDevices().then((devices) => {
devices.forEach(device => {
switch(device.kind) {
devices.forEach((device) => {
switch (device.kind) {
case 'audioinput':
audioSources.push({ device, label: device.label || `audioinput` });
audioSources.push({ device, label: device.label || 'audioinput' });
break;
case 'videoinput':
videoSources.push({ device, label: device.label || `videoinput` });
videoSources.push({ device, label: device.label || 'videoinput' });
break;
default: console.log('Other input type detected.');
}
})
});
});
return { audioSources, videoSources };
},

initializeCamera: ({ videoElement, audioDeviceId, videoDeviceId, height, width, ideal, max, facingMode = 'environment' }) => {
initializeCamera: ({
audioDeviceId, videoDeviceId, height, width, ideal, max, facingMode = 'environment',
}) => {
const constraints = {
audio: {
deviceId: { exact: audioDeviceId },
@@ -38,12 +42,7 @@ const CameraKitWeb = {
facingMode,
},
};
const gotStream = (stream) => {
window.stream = stream;
videoElement.srcObject = stream;
videoElement.play();
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(handleError);
return navigator.mediaDevices.getUserMedia(constraints);
},

takePicture: ({ videoElement }) => {
@@ -55,6 +54,40 @@ const CameraKitWeb = {
canvas.height = videoElement.videoHeight;
context.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight);
return canvas.toDataURL('image/png');
}
}
},

startRecording: ({ stream }) => {
const mediaSource = new MediaSource();
recordedBlobs = [];

const handleDataAvailable = (event) => {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
};
mediaSource.addEventListener('sourceopen', () => {
mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
}, false);
try {
mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp8' });
} catch (e) {
console.error('Exception while creating MediaRecorder:', e);
return;
}
console.log('Created MediaRecorder', mediaRecorder);
mediaRecorder.onstop = (event) => {
console.log('Recorder stopped: ', event);
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
console.log('MediaRecorder started', mediaRecorder);
},

stopRecording: () => {
mediaRecorder.stop();
return new Blob(recordedBlobs, { type: 'video/webm' });
},
};


export default CameraKitWeb;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
"babel-plugin-module-resolver": "^3.1.1",
"body-parser": "^1.18.3",
"dotenv": "^6.0.0",
"eslint-plugin-react": "^7.11.1",
"express": "^4.16.3",
"express-sslify": "^1.2.0",
"next": "^7.0.0",
87 changes: 68 additions & 19 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -9,72 +9,121 @@ class Example extends React.Component {
videoSources: [],
image: undefined,
imageTaken: false,
}
stream: undefined,
videoTaken: undefined,
};
}

handleError = (error) => {
console.log('Error: ', error);
}

getDevices = () => {
CameraKitWeb.getDevices().then(({ audioSources, videoSources }) => {
this.setState({ audioSources, videoSources });
}).catch(error => console.log(error));
}).catch(this.handleError);
};

gotStream = (stream) => {
this.setState({ stream });
this.src.srcObject = stream;
this.src.play();
};

requestCamera = () => {
CameraKitWeb.initializeCamera({
videoElement: this.video,
audioDeviceId: this.audioSource.value,
videoDeviceId: this.videoSource.value,
});
}).then(this.gotStream).catch(this.handleError);
}

takePicture = () => {
this.setState({
imageTaken: true,
image: CameraKitWeb.takePicture({
videoElement: this.video,
videoElement: this.src,
}),
}, this.showPicture);
}

showPicture = () => {
console.log(this.imageContainer);
this.imageContainer.src = this.state.image;
const { image } = this.state;
this.imageContainer.src = image;
}

downloadPicture = () => {
const a = document.createElement('a');
a.download = `CKW-${new Date}`;
a.href = this.state.image;
const { image } = this.state;
a.download = `CKW-${new Date()}`;
a.href = image;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}

startRecording = () => {
const { stream } = this.state;
CameraKitWeb.startRecording({ stream });
this.setState({ recording: true });
}

stopRecording = () => {
const buffer = CameraKitWeb.stopRecording();
this.setState({ video: buffer, recording: false, videoTaken: true }, () => {
const { video } = this.state;
this.out.src = null;
this.out.srcObject = null;
this.out.src = window.URL.createObjectURL(video);
this.out.controls = true;
this.out.play();
});
}

downloadVideo = () => {
const a = document.createElement('a');
const { video } = this.state;
a.download = `CKW-${new Date()}`;
a.href = window.URL.createObjectURL(video);
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}

render() {
const {
audioSources, videoSources, imageTaken, recording, videoTaken,
} = this.state;
return (
<div>
<button onClick={this.getDevices}>Get Audio/Video Devices</button>
<select ref={select => this.audioSource = select} >
<button type="button" onClick={this.getDevices}>Get Audio/Video Devices</button>
<select ref={(select) => { this.audioSource = select; }}>
{
this.state.audioSources.map(source => (
audioSources.map(source => (
<option key={source.label} value={source.device.deviceId}>{source.label}</option>
))
}
</select>
<select ref={select => this.videoSource = select }>
<select ref={(select) => { this.videoSource = select; }}>
{
this.state.videoSources.map(source => (
videoSources.map(source => (
<option key={source.label} value={source.device.deviceId}>{source.label}</option>
))
}
</select>
<br />
<button onClick={this.requestCamera}>Request Audio/Video Stream</button>
<video ref={video => (this.video = video)}></video>
<button type="button" onClick={this.requestCamera}>Request Audio/Video Stream</button>
<video ref={(video) => { this.src = video; }} />
<br />
<button type="button" onClick={this.takePicture}>Take Picture</button>
{imageTaken && (<img alt="capture of webcam screen" ref={(img) => { this.imageContainer = img; }} />)}
{imageTaken && (<button type="button" onClick={this.downloadPicture}>Download Image</button>)}
<br />
<button onClick={this.takePicture}>Take Picture</button>
{this.state.imageTaken && (<img ref={img => this.imageContainer = img}></img>)}
{this.state.imageTaken && (<button onClick={this.downloadPicture}>Download Image</button>)}
<button type="button" disabled={recording} onClick={this.startRecording}>Start Recording</button>
<button type="button" disabled={!recording} onClick={this.stopRecording}>Stop Recording</button>
{videoTaken && (<video ref={(video) => { this.out = video; }} />)}
{videoTaken && (<button type="button" disabled={recording} onClick={this.downloadVideo}>Download Video</button>)}
</div>
);
}
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -2627,6 +2627,16 @@ eslint-plugin-jsx-a11y@^6.1.1:
has "^1.0.3"
jsx-ast-utils "^2.0.1"

eslint-plugin-react@^7.11.1:
version "7.11.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c"
dependencies:
array-includes "^3.0.3"
doctrine "^2.1.0"
has "^1.0.3"
jsx-ast-utils "^2.0.1"
prop-types "^15.6.2"

eslint-restricted-globals@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7"