{"id":13553485,"url":"https://github.com/binarykitchen/videomail-client","last_synced_at":"2025-04-05T06:07:50.860Z","repository":{"id":25429393,"uuid":"28858924","full_name":"binarykitchen/videomail-client","owner":"binarykitchen","description":"A wicked npm package to record videos directly in the browser, wohooo!","archived":false,"fork":false,"pushed_at":"2025-03-21T23:28:25.000Z","size":102110,"stargazers_count":56,"open_issues_count":12,"forks_count":19,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-26T05:34:25.629Z","etag":null,"topics":["audio-recorder","javascript","video-recorder","video-recording","videomail","webcam"],"latest_commit_sha":null,"homepage":"https://videomail.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/binarykitchen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"audit-ci.json","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-01-06T10:47:18.000Z","updated_at":"2025-03-21T23:28:29.000Z","dependencies_parsed_at":"2024-08-01T12:23:15.833Z","dependency_job_id":"96d4bb53-1747-46d1-a66a-d23f2338d4fa","html_url":"https://github.com/binarykitchen/videomail-client","commit_stats":{"total_commits":1647,"total_committers":3,"mean_commits":549.0,"dds":"0.0012143290831815312","last_synced_commit":"8a7ccdf9e3a419f17cca550563dd40df9848c519"},"previous_names":[],"tags_count":628,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarykitchen%2Fvideomail-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarykitchen%2Fvideomail-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarykitchen%2Fvideomail-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binarykitchen%2Fvideomail-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binarykitchen","download_url":"https://codeload.github.com/binarykitchen/videomail-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246140582,"owners_count":20729802,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio-recorder","javascript","video-recorder","video-recording","videomail","webcam"],"created_at":"2024-08-01T12:02:26.110Z","updated_at":"2025-03-29T05:08:01.609Z","avatar_url":"https://github.com/binarykitchen.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# videomail-client ✉\n\n[![Test Runner for videomail-client](https://github.com/binarykitchen/videomail-client/actions/workflows/ci.yml/badge.svg)](https://github.com/binarykitchen/videomail-client/actions/workflows/ci.yml)\n\n[![npm][npm-image]][npm-url]\n[![downloads][downloads-image]][downloads-url]\n[![Netlify Status](https://api.netlify.com/api/v1/badges/3c9df5b4-8b85-4081-950a-d5df2dbd9926/deploy-status)](https://app.netlify.com/sites/videomail-client/deploys)\n\n[npm-image]: https://img.shields.io/npm/v/videomail-client.svg?style=flat\n[npm-url]: https://npmjs.org/package/videomail-client\n[downloads-image]: https://img.shields.io/npm/dm/videomail-client.svg?style=flat\n[downloads-url]: https://npmjs.org/package/videomail-client\n\nRecord videos in contact forms!\n\nFinally you can encode any webcam recordings from modern browsers and mobiles into MP4 + WebM within seconds.\nThis without the need for Flash, Java nor any other plugins / addons. Just TypeScript, compiled into ESM (ES2022) with their declarations.\n\n- \u003ca href=\"#storybook\"\u003eStorybook (examples)\u003c/a\u003e\n- \u003ca href=\"#demo\"\u003eDemo / Fully working version\u003c/a\u003e\n- \u003ca href=\"#options\"\u003eOptions\u003c/a\u003e\n- \u003ca href=\"#api\"\u003eAPI\u003c/a\u003e\n- \u003ca href=\"#form\"\u003eForm Submissions\u003c/a\u003e\n- \u003ca href=\"#whatisstored\"\u003eWhat gets stored on the videomail server?\u003c/a\u003e\n- \u003ca href=\"#whitelist\"\u003eWhitelist\u003c/a\u003e\n- \u003ca href=\"#compatibility\"\u003eBackward compatibility\u003c/a\u003e\n- \u003ca href=\"#addons\"\u003eAddons\u003c/a\u003e\n- \u003ca href=\"#notes\"\u003eNotes\u003c/a\u003e\n\n\u003ca name=\"storybook\"\u003e\u003c/a\u003e\n\n## Storybook (examples)\n\nTo check out some examples in your browser, just run these two commands:\n\n1. `npm install`\n2. `npm run storybook`\n\nThat's it. Easy as apple pie.\n\n\u003ca name=\"demo\"\u003e\u003c/a\u003e\n\n## Demo\n\nA mirror of latest videomail-client can be seen on [videomail-client.netlify.com](https://videomail-client.netlify.com/)\n\n### Real world usages\n\nCheck out the full version with all its features on [videomail.io](https://videomail.io) itself. Aim is to turn this into a stable product in the near future with some external assistance.\n\nOn that site I just include `import { VideomailClient}  from \"videomail-client\"` in the app logic.\n\nAnother live example would be https://seeflow.co.nz/contact or https://www.deaf.org.nz/contact\nThere are plenty if you just ask us. And way more will follow, we are rolling ...\n\n\u003ca name=\"options\"\u003e\u003c/a\u003e\n\n## Options\n\nThere are many options you can pass onto the VideomailClient constructor. Check out the annotated source code at [src/options.ts](https://github.com/binarykitchen/videomail-client/blob/master/src/options.ts)\n\nIn most cases, these defaults are good enough. But `siteName` should be changed when you deploy your own site, see \u003ca href=\"#whitelist\"\u003eWhitelist\u003c/a\u003e.\n\nLooking at the examples in the `/src/stories` folder should give you some ideas how to use these options.\n\n\u003ca name=\"api\"\u003e\u003c/a\u003e\n\n## API\n\n- \u003ca href=\"#constructor\"\u003e`new VideomailClient()`\u003c/a\u003e\n- \u003ca href=\"#on\"\u003e`videomailClient.on()`\u003c/a\u003e\n- \u003ca href=\"#show\"\u003e`videomailClient.show()`\u003c/a\u003e\n- \u003ca href=\"#hide\"\u003e`videomailClient.hide()`\u003c/a\u003e\n- \u003ca href=\"#record\"\u003e`videomailClient.record()`\u003c/a\u003e\n- \u003ca href=\"#replay\"\u003e`videomailClient.replay()`\u003c/a\u003e\n- \u003ca href=\"#startOver\"\u003e`videomailClient.startOver()`\u003c/a\u003e\n- \u003ca href=\"#getByAlias\"\u003e`videomailClient.getByAlias()`\u003c/a\u003e\n- \u003ca href=\"#getByKey\"\u003e`videomailClient.getByKey()`\u003c/a\u003e\n- \u003ca href=\"#unload\"\u003e`videomailClient.unload()`\u003c/a\u003e\n- \u003ca href=\"#hide\"\u003e`videomailClient.hide()`\u003c/a\u003e\n- \u003ca href=\"#isDirty\"\u003e`videomailClient.isDirty()`\u003c/a\u003e\n- \u003ca href=\"#isRecording\"\u003e`videomailClient.isRecording()`\u003c/a\u003e\n- \u003ca href=\"#isBuilt\"\u003e`videomailClient.isBuilt()`\u003c/a\u003e\n- \u003ca href=\"#submit\"\u003e`videomailClient.submit()`\u003c/a\u003e\n- \u003ca href=\"#getLogLines\"\u003e`videomailClient.getLogLines()`\u003c/a\u003e\n\n\u003ca name=\"constructor\"\u003e\u003c/a\u003e\n\n### new VideomailClient([options])\n\nThe constructor accepts a JSON with optional \u003ca href=\"#options\"\u003eoptions\u003c/a\u003e. Example:\n\n```ts\nconst videomailClient = new VideomailClient({ siteName: \"my site name\" });\n```\n\n\u003ca name=\"on\"\u003e\u003c/a\u003e\n\n### videomailClient.on([event,] [callback])\n\nThe VideomailClient class is inherited from EventEmitter and emits lots of useful events for your app. Here an example:\n\n```ts\nvideomailClient.on(\"FORM_READY\", () =\u003e {\n  // form is ready for recording\n});\n\nvideomailClient.on(\"SUBMITTED\", ({ videomail, response }) =\u003e {\n  // continue with your own app logic in your javascript code if you want to process\n  // something else further after form submission.\n});\n```\n\n#### Supported events:\n\nCheck them out at [src/types/events/index.ts](https://github.com/binarykitchen/videomail-client/blob/master/src/types/events/index.ts)\n\nThey should be self-explanatory. If not, ask for better documentation. Then, some of these events may come with parameters.\n\nThe 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.\n\nBy 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.\n\n\u003ca name=\"show\"\u003e\u003c/a\u003e\n\n### videomailClient.show()\n\nAutomatically fills the DOM with a form for video recording. By default the HTML element with the ID `videomail` will be filled, see options.\n\n\u003ca name=\"record\"\u003e\u003c/a\u003e\n\n### videomailClient.record()\n\nForcefully starts recording without the need to press on a record button. Useful for special situations.\n\n\u003ca name=\"replay\"\u003e\u003c/a\u003e\n\n### videomailClient.replay(videomail[, parentElementId])\n\nManually adds a video container for the given videomail inside the parent element. See stories for some inspiration.\n\nIf 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.\n\nAlso note that, when the parent element already contains a video container like this\n\n```html\n\u003cvideo class=\"replay\"\u003e\u003c/video\u003e\n```\n\nthen this will be used instead of adding a new dom element.\n\n\u003ca name=\"startOver\"\u003e\u003c/a\u003e\n\n### videomailClient.startOver()\n\nStart all over again, resets everything and go back to the ready state. Useful if you want to submit another videomail within the same instance.\n\n\u003ca name=\"getByAlias\"\u003e\u003c/a\u003e\n\n### videomailClient.getByAlias(alias)\n\nQueries a videomail (JSON) asynchronously by a given alias for further queries or processing. There are two ways to get the alias:\n\n1. The form submission to your own server has it under `videomail_alias` in the form body.\n2. Get the alias from the `submitted` event and use it further within your code.\n\n\u003ca name=\"unload\"\u003e\u003c/a\u003e\n\n### videomailClient.unload()\n\nManually unloads the webcam and all other internal event listeners.\n\n\u003ca name=\"hide\"\u003e\u003c/a\u003e\n\n### videomailClient.hide()\n\nHides all the visuals (but does not unload anything).\n\n\u003ca name=\"isDirty\"\u003e\u003c/a\u003e\n\n### videomailClient.isDirty()\n\nReturns 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.\n\n\u003ca name=\"isRecording\"\u003e\u003c/a\u003e\n\n### videomailClient.isRecording()\n\nReturns true when a video is currently being recorded.\n\n\u003ca name=\"submit\"\u003e\u003c/a\u003e\n\n### videomailClient.submit()\n\nFor advanced use only: especially when the submit button is covered with other HTML layers and the videomail client fails to process the click event.\nCalling this function will manually trigger a submission of the recorded videomail. But only when everything else is valid. Nothing will happen when invalid.\n\n\u003ca name=\"getLogLines\"\u003e\u003c/a\u003e\n\n### videomailClient.getLogLines()\n\nFor 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.\n\n\u003ca name=\"whatisstored\"\u003e\u003c/a\u003e\n\n## What gets stored on the videomail server?\n\nHere is an example JSON showing what videomail meta data exists, gets stored on the server and you can grab yourself for further use.\nIt's emitted in the SUBMITTED event under the videomail object:\n\n```json\n{\n  \"subject\": \"some subject\",\n  \"from\": \"some@sender.com\",\n  \"body\": \"A text body\",\n  \"recordingStats\": {\n    \"avgFps\": 15.151515151515152,\n    \"wantedFps\": 15,\n    \"avgInterval\": 62.09090909090909,\n    \"wantedInterval\": 66.66666666666667,\n    \"intervalSum\": 683,\n    \"framesCount\": 11,\n    \"videoType\": \"webm\",\n    \"waitingTime\": 192\n  },\n  \"width\": 320,\n  \"height\": 240,\n  \"videomailClientVersion\": \"2.4.11\",\n  \"siteName\": \"videomail-client-demo\",\n  \"alias\": \"some-subject-183622500964\",\n  \"dateCreated\": 1541130589811,\n  \"url\": \"https://videomail.io/videomail/some-subject-150322500964\",\n  \"key\": \"11e8-de52-55ac2630-b22b-71959562a989\",\n  \"expirationPretty\": \"1 hour\",\n  \"expiresAfter\": 1541134189811,\n  \"siteTitle\": \"Videomail Client Example\",\n  \"webm\": \"https://videomail.io/videomail/some-subject-183622500964/type/webm/\",\n  \"poster\": \"https://videomail.io/videomail/some-subject-183622500964/poster/\",\n  \"dateCreatedPretty\": \"Nov 2, 2018, 4:49 PM\",\n  \"expiresAfterPretty\": \"Nov 2, 2018, 5:49 PM\",\n  \"expiresAfterIso\": \"2018-11-02T04:49:49.811Z\"\n}\n```\n\nYou also can get all the above using the `videomailClient.getByKey()` API call.\n\n\u003ca name=\"form\"\u003e\u003c/a\u003e\n\n## Form Submissions\n\nBy default the videomail-client interrupts the form submission with `e.preventDefault()` and submits the videomail itself to the videomail server first. The videomail server replies with useful data, such as the videomail alias, other meta data and only then the real form submission is resumed.\n\nIf this doesn't seem to work on your side, then this is mostly because the form and the submit button couldn't be found and the submission event is fired too late. To fix this, you'll need to correct the selectors under options. Here are the important ones regarding forms:\n\n```ts\nselectors: {\n  \"formId\": null,\n  \"submitButtonId\": null,\n  \"submitButtonSelector\": null\n},\n```\n\nWhen these are null (defaults), the videomail-client tries to detect these automatically. But it can happen that detection fails because the form is somewhere else under the DOM or the submit button does not have the `type=submit` etc.\n\n### Include videomail meta data in Form Submissions\n\nIf you want to include videomail meta data in the form submission to your own server, enable the `submitWithVideomail` option.\nOtherwise only the videomail alias is in the form body and will have to call `videomail.getByAlias(alias)` to retrieve these later on.\n\n\u003ca name=\"whitelist\"\u003e\u003c/a\u003e\n\n## Whitelist\n\nExamples will work right away on [https://localhost:8443](https://localhost:8443). 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.\n\nIn 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](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).\n\n\u003ca name=\"compatibility\"\u003e\u003c/a\u003e\n\n## Backward compatibility\n\nForget the old IE, Safari below version 11 and ancient iPhones/iPads because they don't support `getUserMedia()`. Do not blame me but Apple + Microsoft _chuckle_ - for now, these browsers work like a charm:\n\n- Firefox \u003e= 34\n- Google Chrome \u003e= 32\n- Microsoft Edge \u003e= 12\n- Internet Explorer \u003e= 12\n- Opera \u003e= 26\n- Chrome for Android \u003e= 39\n- Android Browser \u003e= 37\n- Safari \u003e= 11\n\nSource: [http://caniuse.com/#search=getUserMedia](http://caniuse.com/#search=getUserMedia)\n\nPS: 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.\n\n\u003ca name=\"addons\"\u003e\u003c/a\u003e\n\n## Addons\n\nThere is a Videomail WordPress addon, wicked!\nhttps://wordpress.org/plugins/videomail-for-ninja-forms/\n\nIt'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.\n\n\u003ca name=\"notes\"\u003e\u003c/a\u003e\n\n## Notes\n\n### Changelog\n\nToo hard to maintain. Just do `git log` or look here\nhttps://github.com/binarykitchen/videomail-client/commits/master\n\n### Noise\n\nHere some noise about Videomail in the wild:\n\n- [LimpingChicken](http://limpingchicken.com/2017/06/29/michael-heuberger-ive-created-a-web-form-to-send-emails-in-sign-language/)\n\n### Unfinished Metamorphosis (aka Development)\n\nThis is just the beginning. I will add a lot more over time.\n\nBear 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.\n\n### Credits\n\nThese guys helped inspired me for this awesome project. Thank you so much:\n\n- Heath Sadler (Designer)\n- Stefan Weber (Designer)\n- Zack Best (Jurist)\n- Sonia Pivac (Designer)\n- Dominic Tarr (Boat Builder)\n- Daniel Ly (Developer)\n- Nicholas Buchanan (No idea)\n- Kelvin Wong (Gamer)\n- Isaac Johnston (Consultant)\n\nThey all deserve lots of love in return. Thank you so much.\n\n### Code quality\n\nI 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 bug fixes come first before perfection otherwise you'll loose users. Reality you know.\n\n### Final philosophy\n\nThis planet is completely sold. And talk is overrated. That's why my primary goal is not to turn this into a commercial product, yet to promote a cool but underestimated language: Sign Language.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinarykitchen%2Fvideomail-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinarykitchen%2Fvideomail-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinarykitchen%2Fvideomail-client/lists"}