| Table of Contents |
|---|
The example to show stream snapshot capturing in local browser
...
On the screenshot below, stream snapshot is already captured
When publishing starts, video is playin in 'Local' element at left side.
After clicking 'Take a snapshot' button snapshot is capturing from HTML5 video element, when is shown in 'Snaphot' element at right side.
...
To analyze the code let's take a stream-local-snapshot.js version with hash 1d572d0 ecbadc3, which is available available here and can be downloaded in build build 2.0.164212.
1. API initialization.
Flashphoner.init() code
| Code Block | ||||
|---|---|---|---|---|
| ||||
Flashphoner.init({flashMediaProviderSwfLocation: '../../../../media-provider.swf'}); |
2. HTML page elements initialization and storing snapshot preview picture size
| Code Block | ||||
|---|---|---|---|---|
| ||||
localVideo = document.getElementById("localVideo");
snapshotImg = document.getElementById("snapshotImg");
canvas = document.getElementById("canvas");
//preview size
snapshotImgSize = {
w: snapshotImg.width,
h: snapshotImg.height
}; |
...
Flashphoner.createSession() code
| Code Block | ||||
|---|---|---|---|---|
| ||||
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
//session connected, start streaming
startStreaming(session);
...
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus(SESSION_STATUS.DISCONNECTED);
$('#url').prop('disabled', false);
onUnpublished();
...
}).on(SESSION_STATUS.FAILED, function(){
setStatus(SESSION_STATUS.FAILED);
$('#url').prop('disabled', false);
onUnpublished();
...
}); |
4. Receiving the event confirming successful connection.
ConnectionStatusEvent ESTABLISHED ESTABLISHED code
| Code Block | ||||
|---|---|---|---|---|
| ||||
Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
//session connected, start streaming
startStreaming(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
...
}).on(SESSION_STATUS.FAILED, function(){
...
}); |
5. Stream publishin.
session.createStream(), stream.publish() code
The following parameters are passed to createStream():
...
StreamStatusEvent PUBLISHING code
| Code Block | ||||
|---|---|---|---|---|
| ||||
session.createStream({
...
}).on(STREAM_STATUS.PUBLISHING, function(publishStream){
setStatus(STREAM_STATUS.PUBLISHING);
onPublishing(publishStream);
}).on(STREAM_STATUS.UNPUBLISHED, function(){
...
}).on(STREAM_STATUS.FAILED, function(){
...
}).publish(); |
7. Snapshot capture function invokation by button click
| Code Block | ||||
|---|---|---|---|---|
| ||||
$("#snapshotBtn").off('click').click(function(){
snapshot(stream);
}).prop('disabled', false); |
8. Frame captured drawing on the canvas and converting to PNG
| Code Block | ||||
|---|---|---|---|---|
| ||||
function snapshot(stream) {
let video = document.getElementById(stream.id());
let canvasContext = canvas.getContext("2d");
if (video === undefined) {
console.log("Failed to get video item for stream " + stream.name);
} else {
let videoSize = {
w: video.videoWidth,
h: video.videoHeight
};
// Draw snapshot on hidden canvas in full video size
canvas.width = videoSize.w;
canvas.height = videoSize.h;
canvasContext.drawImage(video, 0, 0, canvas.width, canvas.height);
let data = canvas.toDataURL('image/png');
if (data === undefined) {
console.log("Failed to get image data from canvas");
} else {
...
}
}
} |
9. Snapshot picture scaling to display preview and adding data to img element
| Code Block | ||||
|---|---|---|---|---|
| ||||
function snapshot(stream) {
let video = document.getElementById(stream.id());
let canvasContext = canvas.getContext("2d");
if (video === undefined) {
console.log("Failed to get video item for stream " + stream.name);
} else {
...
if (data === undefined) {
console.log("Failed to get image data from canvas");
} else {
// Downscale snapshot preview keeping video aspect ratio
let previewSize;
previewSize = downScaleToFitSize(videoSize.w, videoSize.h, snapshotImgSize.w, snapshotImgSize.h);
console.log("previewSize: " + previewSize.w + "x" + previewSize.h);
snapshotImg.style.width = previewSize.w + "px";
snapshotImg.style.height = previewSize.h + "px";
// Snapshot preview vertical align
let margin = 0;
if (snapshotImgSize.h - previewSize.h > 1) {
margin = Math.floor((snapshotImgSize.h - previewSize.h) / 2);
}
snapshotImg.style.margin = margin + "px auto";
// Set image data to snapshot page item. "Open image in new tab" or "Save image as" will open full size snapshot
snapshotImg.setAttribute('src', data);
}
}
} |
10. Helper function to scale the picture
| Code Block | ||||
|---|---|---|---|---|
| ||||
function downScaleToFitSize(videoWidth, videoHeight, dstWidth, dstHeight) {
let newWidth, newHeight;
let videoRatio = videoWidth / videoHeight;
let dstRatio = dstWidth / dstHeight;
if (dstRatio > videoRatio) {
newHeight = dstHeight;
newWidth = Math.floor(videoRatio * dstHeight);
} else {
newWidth = dstWidth;
newHeight = Math.floor(dstWidth / videoRatio);
}
return {
w: newWidth,
h: newHeight
};
} |
11. Stream stopping.
stream.stop() code
| Code Block | ||||
|---|---|---|---|---|
| ||||
function onPublishing(stream) {
$("#publishBtn").text("Stop").off('click').click(function(){
$(this).prop('disabled', true);
stream.stop();
}).prop('disabled', false);
...
} |
...
StreamStatusEvent UNPUBLISHED code
| Code Block | ||||
|---|---|---|---|---|
| ||||
session.createStream({
...
}).on(STREAM_STATUS.PUBLISHING, function(publishStream){
...
}).on(STREAM_STATUS.UNPUBLISHED, function(){
setStatus(STREAM_STATUS.UNPUBLISHED);
//enable start button
onUnpublished();
}).on(STREAM_STATUS.FAILED, function(){
...
}).publish();
|

