JavaScript CSS
Latest commit 3f5ebdb Aug 15, 2017 @binarykitchen Merge tag '2.0.19' into develop
Completing release of 2.0.19 2.0.19

* tag '2.0.19':
  Final commit of version 2.0.19

README.md

videomail-client ✉

Build Status npm downloads gratipay browserstack

Record videos in contact forms!

Finally you can encode any webcam recordings from modern browsers and mobiles into MP4 + WebM within seconds. This without the need for Flash, Java nor any other plugins / addons. Just JavaScript written in ES6.

Examples

To run the examples in your browser with Gulp, just do:

  1. npm install
  2. gulp examples to ignite a static server and
  3. open https://localhost:8080 in your browser

(just ignore the invalid certificate warning, this will be fixed soon)

Best is to study /examples/contact_form_json.html which demonstrates how easy it is to integrate the videomail client into your own contact form.

Beware that all must run over HTTPs. Google Chrome and soon other browsers won't allow the use of getUserMedia() on insecure origins.

Dead simple example (just record and replay)

<html>
  <body>
    <div id="videomail"></div>
    <script src="/dist/videomail-client.js"></script>
    <script>
      var VideomailClient = require('videomail-client'), // load videomail client package
          videomailClient = new VideomailClient({        // instantiate with some options
            verbose:       true,                         // prints additional info to console
            disableSubmit: true                          // disable submissions to keep example simple
          })

      // this will load your webcam, fill the placeholder containing
      // the `id="videomail"` with HTML and CSS code, place buttons and much more.
      videomailClient.show()
    </script>
  </body>
</html>

The included JS file /dist/videomail-client.js is already browserified and lies in the dist folder.

If you remove disableSubmit, then you will see a submit button to post the video and make it persistent. This requires a bit more code, see examples directory.

Demo / Fully working version

Check out the full version with all its features on videomail.io itself. Aim is to turn this into a stable product in the near future with some external assistance.

That site runs on AngularJS where I just include require('videomail-client') in the app logic and bundle all that through Browserify.

Another live example would be https://seeflow.co.nz/contact/. More will follow ...

Options

There are many options you can pass onto the VideomailClient constructor. Check out the annotated source code at src/options.js

In most cases, these defaults are good enough. But siteName should be changed when you deploy your own site, see Whitelist.

Looking at the examples in the /examples folder should give you some ideas how to use these options.

API

new VideomailClient([options])

The constructor accepts a JSON with optional options. Example:

var videomailClient = new VideomailClient({siteName: 'my site name'})

videomailClient.on([event,] [callback])

The VideomailClient class is inherited from EventEmitter and emits lots of useful events for your app. Here an example:

videomailClient.on('FORM_READY', function() {
  // form is ready for recording
})

videomailClient.on('SUBMITTED', function(videomail, response) {
  // continue with your own app logic
  // check out /examples/contact_form.html on how to integrate into your contact form
})

Supported events:

Check them out at src/events.js

They should be self-explanatory. If not, ask for better documentation. Then, some of these events may come with parameters.

The videomail client already comes with internal error handling mechanism so there is no need to add code to display errors. But depending on your app logic you might want to process errors further with your own error listeners.

By the way, all videomail errors are instances of VideomailError, inherited from the native Error class and come with additional attributes, useful for debugging weird errors.

videomailClient.show()

Automatically fills the DOM with a form for video recording. By default the HTML element with the ID videomail will be filled, see options.

videomailClient.replay(videomail[, parentElement])

Manually adds a video container for the given videomail inside the parent element. This is mostly called after a successful submission. See /examples/direct_submit.html or /examples/contact_form.html for some inspiration.

If the parentElement is an ID (string), then it will be resolved into a DOM element internally. If no parent element is given, then a replay container within the containerId is automatically generated.

Also note that, when the parent element already contains a video container like this

<video class="replay"></video>

then this will be used instead of adding a new dom element.

Furthermore the replay() method also detects whether the parent element has placeholders to fill with form data. To understand this better, check out how the subject in the /examples/direct_submit.html example is being displayed upon replay.

videomailClient.startOver()

Start all over again, resets everything and go back to the ready state. Useful if you want to submit another videomail within the same instance.

videomailClient.get(key, cb)

Queries a videomail (JSON) by a given key. When submitted, you get the key from the submitted event and can use that for storage and future queries of videomails.

videomailClient.canRecord()

An utility function which returns true if the current browser is capable of webcam recording. It returns false for incompatible browsers.

videomailClient.unload()

Manually unloads the webcam and all other internal event listeners. Can be used in conjunction with single page apps, for example with AngularJS' destroy event:

$scope.$on('$destroy', videomailClient.unload.bind(videomailClient))

videomailClient.hide()

Hides all the visuals (but does not unload anything).

videomailClient.isDirty()

Returns true when a video has been recorded and a form exists. Useful when checking something before closing the window, i.E. this use case: show a window confirmation dialog to make sure the user didn't forget to submit the recorded video.

videomailClient.submit()

For advanced use only: especially when the submit button is covered with other HTML layers and the videomail client fails to process the click event.

Calling this function will manually trigger a submission of the recorded videomail. But only when everything else is valid. Nothing will happen when invalid.

videomailClient.getLogLines()

For advanced use only: returns you a collection of log lines that show what code has been covered recently. Useful if you want to debug something tricky.

Whitelist

Examples will work right away on https://localhost:8080. This is because localhost is whitelisted on the remote Videomail server. https://localhost and https://localhost:443 are whitelisted too for local development. Other IP addresses won't work. If this is a problem, contact me and I can whitelist more.

In other words, if your web server is connected through a domain besides localhost, the Videomail-Client is restricted from sending the media packets to the remote Videomail server which is responsible for storing and sending videomails. To fix that, just lodge a whitelist request at https://videomail.io/whitelist. Then you should get a new site name and a list of whitelisted URLs for your own usage pretty fast (within less than 48 hours).

Backward compatibility

Forget the old IE, Safari and iPhones/iPads because they still don't support getUserMedia(). Do not blame me but Apple + Microsoft chuckle - but these browsers work like a charm:

  • Firefox >= 34
  • Google Chrome >= 32
  • Microsoft Edge >= 12
  • Internet Explorer >= 12
  • Opera >= 26
  • Chrome for Android >= 39
  • Android Browser >= 37

Source: http://caniuse.com/#search=getUserMedia

PS: On Safari and iPhones/iPads you can play the videomails fine without any issues. Repeating: there is just no recording functionality for them yet until Apple made a move.

Super fast global CDN

You can grab the already browserified videomail-client JS file through GitHub's rawgit server which is proxied by MaxCDN's super fast global CDN:

https://cdn.rawgit.com/binarykitchen/videomail-client/<version number>/dist/videomail-client.js

For example for version x.y.z, use this in your production site: https://cdn.rawgit.com/binarykitchen/videomail-client/x.y.z/dist/videomail-client.min.js

If for whatever reason that GitHub CDN doesn't meet your standard, here's another CDN to try: https://cdnjs.com/libraries/videomail-client

Addons

There is a Videomail WordPress addon, wicked! https://ninjaforms.com/extensions/videomail/

It's an extension of the popular form builder called Ninja Forms. When the videomail addon is installed, then you can just drag and drop a live webcam input into the form! And tell what should happen upon submission. So easy.

Notes

Unfinished Metamorphosis (aka Development)

This is just the beginning. I will add a lot more over time.

Bear with me, there are lots of problems to crack, especially with the performance, audio part and some unit tests are missing. I do not want to waste too much time on perfection unless it's proven to work then I rewrite piece by piece.

Credits

These guys helped and/or inspired me for this mad project:

  • Heath Sadler
  • Zack Best
  • Sonia Pivac
  • Isaac Johnston
  • Dominic Tarr
  • Daniel Ly
  • Nicholas Buchanan
  • Kelvin Wong

They all deserve lots of beer and love. That order is irrelevant.

And yes, one more thing: because it is very crucial to make videomail-client work on all browsers, I cannot emphasize enough how important it is to have Browserstack - for instant, live end-to-end tests on any browser or mobile device. Thanks guys!

Code quality

I admit, code isn't top notch and needs lots of rewrites. Believe me or not, I already rewrote about three times in the last four years. Good example that software hardly can be perfect. And since I am already honest here, I think stability and bugfixes come first before perfection otherwise you'll loose users. Reality you know.

Anyway, on the next rewrite I'd probably pick React or better re-frame because the Videomail-Client depends heaviliy on application states.

Final philosophy

This planet is completely sold. And talk is overrated. That's why my primary goal is not to turn this into a commercial product but to promote a cool but underestimated language: Sign Language.