// How to use: // - Works only in browsers supporting getUserMedia HTML5 api, chrome, firefox, android. The browser will ask for permission to use access the camera. // 1. Enter the feed id to publish to. // 2. Enter either the api key or publish key, for non public feeds, an access key is needed to show the live frame if the api key is not used // 3. If you're not using the api key and the feed isn't public, enter the accesskey to allow access to the current feed frame. // 4. Start the webcam and upload frames. var feedId = ""; var apiKey = ""; var publishKey = ""; var accessKey = ""; // required for only 'current live frame' to work for non-public feeds, only if apiKey is not used // the time the frame was recorded, this is optional, current time will be used if not specified var frameTime = ""; var apiBaseUrl = "//www.teleport.nu/api/v1"; // don't cache ajax or content won't be fresh $.ajaxSetup({ cache: false }); var url = apiBaseUrl + "/frame-set?feedid=" + feedId + "&frametime=" + frameTime + "&apikey=" + apiKey + "&publishkey=" + publishKey; var liveFrameUrl = apiBaseUrl + "/frame-get?feedid=" + feedId + "&sizecode=480p" + "&apikey=" + apiKey + "&accesskey=" + accessKey; // load the current live frame if (feedId) { $("#liveFrame").attr('src', liveFrameUrl + '&jsfiddlecb=' + Math.random()); } function uploadFormData(formData) { if (!feedId) { alert("*** Specify the feed id to publish to. ***"); } // upload the provided form data to Teleport $.ajax({ url: url, method: 'POST', data: formData, async: true, cache: false, contentType: false, enctype: 'multipart/form-data', processData: false, success: function (data, textStatus, jqXHR) { // got the result, just a status code on delete api, http status 200 means upload went ok $("#response").html(jqXHR.status); // update the live frame image, use the cache bust random parameter to force the browser to hit the server, else the new image may not load $("#liveFrame").attr('src', liveFrameUrl + '&jsfiddlecb=' + Math.random()); }, error: function (jqxhr, textStatus, error) { $("#response").html("Error: " + jqxhr.status + ', ' + textStatus + ', ' + error + ', ' + jqxhr.responseText); $("#liveFrame").attr('src', ""); } }); } // webcam code, should work in chrome, firefox and opera, android var video = document.querySelector('video'); var canvas = document.querySelector('canvas'); var formData = null; var localMediaStream = null; function hasGetUserMedia() { return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } function startVideo() { if (hasGetUserMedia()) { // Good to go! } else { alert('getUserMedia() is not supported in your browser.'); return; } navigator.anyGetUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; // - resolution selection may not be supported by every browser navigator.anyGetUserMedia({ video: { mandatory: { minWidth: 1280, minHeight: 720, maxWidth: 1920, maxHeight: 1080 } }, audio: false }, function (stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; $("#captureButton").removeAttr('disabled'); }, function (e) { console.log('Reeeejected!', e); }); } function captureFrame() { if (localMediaStream) { canvas.width = video.videoWidth; canvas.height = video.videoHeight; var ctx = canvas.getContext('2d'); ctx.drawImage(video, 0, 0); canvas.toBlob(function (blob) { if (console) { console.log(blob); } formData = new FormData(); formData.append('file', blob, "jsfiddleimage.jpg"); $("#uploadButton").removeAttr('disabled'); }, "image/jpeg"); //img.src = canvas.toDataUrl(); } } // ui //video.addEventListener('click', captureFrame, false); $("#startVideoButton").click(function () { startVideo(); }); $("#stopVideoButton").click(function () { if (localMediaStream) { localMediaStream.stop(); } }); $("#captureButton").click(function () { captureFrame(); }); $("#uploadButton").click(function () { uploadFormData(formData); }); // canvas to blob polyfill, browsers don't really support this well ! function (a) { "use strict"; var b = a.HTMLCanvasElement && a.HTMLCanvasElement.prototype, c = a.Blob && function () { try { return Boolean(new Blob) } catch (a) { return !1 } }(), d = c && a.Uint8Array && function () { try { return 100 === new Blob([new Uint8Array(100)]).size } catch (a) { return !1 } }(), e = a.BlobBuilder || a.WebKitBlobBuilder || a.MozBlobBuilder || a.MSBlobBuilder, f = (c || e) && a.atob && a.ArrayBuffer && a.Uint8Array && function (a) { var b, f, g, h, i, j; for (b = a.split(",")[0].indexOf("base64") >= 0 ? atob(a.split(",")[1]) : decodeURIComponent(a.split(",")[1]), f = new ArrayBuffer(b.length), g = new Uint8Array(f), h = 0; h < b.length; h += 1) g[h] = b.charCodeAt(h); return i = a.split(",")[0].split(":")[1].split(";")[0], c ? new Blob([d ? g : f], { type: i }) : (j = new e, j.append(f), j.getBlob(i)) }; a.HTMLCanvasElement && !b.toBlob && (b.mozGetAsFile ? b.toBlob = function (a, c, d) { d && b.toDataURL && f ? a(f(this.toDataURL(c, d))) : a(this.mozGetAsFile("blob", c)) } : b.toDataURL && f && (b.toBlob = function (a, b, c) { a(f(this.toDataURL(b, c))) })), "function" == typeof define && define.amd ? define(function () { return f }) : a.dataURLtoBlob = f }(this);
<b>Teleport webcam frame upload</b> <!--based on https://github.com/leemachin/say-cheese --> <br/> <br/> <button id="startVideoButton">Start video</button> <button id="stopVideoButton">Stop video</button> <br/>Live stream: <br/> <video autoplay style="max-height: 160px"></video> <br/> <br/> <input id="captureButton" type="button" value="Capture" disabled /> <br/>Captured frame: <br/> <canvas style="max-height: 160px"></canvas> <br/> <input id="uploadButton" type="button" value="Upload" disabled /> <br/> <br/>Upload response: <div id="response"></div> <br/> <br/>Current feed live frame: <br/> <img id="liveFrame" src="" style="max-height: 160px" />