Self-hosted service
miroslavpejic85/call-me avatar
miroslavpejic85/call-me

MiroTalk CME: A Self-Hosted WebRTC Call Button You Can Drop Into Any Page

📞 Open-source, self-hosted WebRTC click-to-call solution for websites. Add a video Call-Me button and let visitors instantly connect with your team through browser-based video communication. Ideal for customer support, sales, consultations, and remote assistance.

764 stars89 forksJavaScriptAGPL-3.0

At a glance

What is it?
MiroTalk CME (repository name call-me) is an AGPL-3.0 Node.js application that puts a browser-based video call behind a URL parameter. It is aimed at teams who want click-to-call on their own server, and it is a poor fit for anyone who cannot operate a WebRTC deployment or accept AGPL terms.
Who is it for?
Adopt MiroTalk CME if you can run a Node.js or Docker service on a public HTTPS host and you want callers to reach named staff through a link rather than an account. Do not adopt it if you cannot terminate TLS yourself, if you need multi-party conferences or call recording, or if AGPL-3.0 does not fit how you ship software.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem: a call button with no vendor in the middle

Most click-to-call widgets are SaaS. The script tag points at someone else's domain, the signalling runs on their servers, and the visitor's browser opens a session you do not control. MiroTalk CME takes the other route: the whole application is a Node.js service you host, and the widget is a link to your own domain. The README describes it as an "Open Source Self-Hosted WebRTC Click-to-Call" solution, and the live demo at cme.mirotalk.com is the author's instance rather than a hosted product you sign up for. The intended users are support desks, sales teams, and consultation practices that want a visitor to press one button and land in a video call with a named person. There is no account system described in the material, no signup step, and no per-seat pricing because there is no vendor. The cost is that you become the operator: the server, the TLS certificate, and the upgrade path are yours.

How a call actually gets routed: the join, call and room parameters

The mechanism is URL-driven rather than API-driven at the entry point. A user joins a room by loading a URL with a user parameter: the README gives http://localhost:8000/join?user=user1 for development and the equivalent https://cme.mirotalk.com/join?user=user1 for production. To make one user call another, the second user loads a URL that adds a call parameter naming the first: /join?user=user2&call=user1. Rooms are an optional third parameter. By default everyone lands in a shared room called Public, and adding &room=Support groups users so that, in the README's words, users "only see and can call others in the same room". The note attached to that section is the constraint worth remembering: the call target must be in the same room as the caller, and if room is omitted both parties fall into Public. That is a simple design, and it means the integration surface for a website is a link, not a JavaScript SDK. The widget example in integration/widget.html is the reference for embedding it. Per-room branding is available by editing the rooms map in public/config.template.js, which sets a name, subtitle, theme color, or GitHub visibility per room. The README is explicit that this is visual only and not a security feature, which is the right caveat to state plainly.

Two install paths, and the files you must copy first

The README documents Node.js and Docker side by side, and both begin with the same two copy steps. You clone the repository, change into the call-me directory, copy public/config.template.js to public/config.js, and copy .env.template to .env. Skipping either copy leaves the application without its configuration. On the Node.js path the remaining commands are npm install and npm start. On the Docker path you additionally copy docker-compose.template.yml to docker-compose.yml, then run docker-compose pull followed by docker-compose up, pulling the image from Docker Hub under the name mirotalk/cme. The README then tells you to open http://localhost:8000, join with a username, select a connected recipient, and click Call. The self-hosting section points at an Ubuntu 22 requirement and install scripts, and the hosted documentation lives at docs.mirotalk.com under the mirotalk-cme path. What the material does not give is a reverse proxy configuration, so anyone deploying beyond localhost will have to work out the WebSocket upgrade and TLS termination themselves; that is the part of the setup most likely to be underestimated, and it is not covered in the README excerpt.

REST API and webhooks: where the app stops being just a widget

The feature list includes a REST API for retrieving connected users, rooms, availability status, active calls, and server stats, plus an endpoint to initiate a call. That matters because it turns the deployment into something a CRM or ticketing system can query: who is online, who is free, and which calls are running. Webhooks cover the other direction, emitting call lifecycle events for user joined, user left, call started, and call ended with duration. Those two surfaces together are what make MiroTalk CME plausible as infrastructure rather than a demo. A support tool could show agent availability from the API and log call duration from the webhook without touching the front end. The README does not reproduce the endpoint paths or the webhook payload schema in the excerpt, so the exact field names have to be read from the documentation before you write an integration against them. Treat that as a real gap: the capability is advertised, the contract is elsewhere.

What the call experience includes, and what it does not

Inside a call the README lists camera, microphone, and speaker switching, real-time chat, video hiding, microphone and camera toggles, screen sharing, file sharing, and hang up. There is a Host Protection mode enabled with a password, and Web Push Notifications so an operator is alerted to an incoming call while the application is in the background. End-to-end encryption is claimed in the feature list. What is absent from the material is just as informative. The README describes "one-to-one video call" as the outcome of the quick start, and nothing in the feature list describes multi-party conferencing, call recording, or transcription. If your requirement is a group consultation with four participants, this is the wrong tool as documented. The branding caveat also deserves weight: room names and colors are cosmetic and do not partition access. If you need real access control over who can enter a room, the material offers the host protection password and nothing else, and you should assume room parameters are guessable.

The deployment boundary: no TURN, no mobile story, no scale claim

WebRTC in browsers needs more than a signalling server when peers sit behind symmetric NAT or restrictive corporate firewalls. The README excerpt does not mention a TURN server, STUN configuration, or any relay component, and it does not claim to solve that class of network. That is the failure mode to plan for: calls that work on your office network and fail for a visitor on a locked-down corporate connection. The material also says nothing about mobile clients, and nothing about how many concurrent calls a single instance handles. The API exposes server stats, which suggests there is something to watch, but no capacity figure is given. Given that, the honest reading is that this is a small-team tool until you measure it yourself. Anyone evaluating it for a high-traffic support desk should load-test their own instance before trusting it, because the repository provides no number to reason from.

The AGPL-3.0 question and the maintenance you inherit

The licence is AGPL-3.0, which is the strongest of the common copyleft licences and, for a network service, the one with the most reach: users interacting with the software over a network are generally entitled to the corresponding source. That is a deliberate choice by the author for a self-hosted product, and it is a different proposition from a permissively licensed library you can embed without thinking about it. This is not legal advice; if you plan to modify the application and expose it to customers, get your own reading of the obligations. On maintenance, the repository shows a last push in September 2026 and no releases retrieved, so there is no versioned release channel to pin to in the material provided. Upgrades on the Docker path run through docker-compose pull against the mirotalk/cme image, which means you are tracking a moving tag unless you pin one yourself. The .env and public/config.js files you create during setup are local and will not be overwritten by a pull, which is the saving grace: your configuration survives, but you are responsible for diffing it against .env.template and config.template.js after each update. Budget for that check on every upgrade.

How it compares with embedding a hosted video SDK

The obvious alternative is a hosted video API such as Daily or Twilio Video, where you write a few lines of client code and the vendor runs the media infrastructure, including the TURN relays that MiroTalk CME's documentation does not describe. The difference in approach is where the signalling and the media path live. With a hosted SDK, the session token is minted by your backend and the peer connections are brokered by the vendor's cloud; you get global relay coverage and a status page, and you pay per minute. With MiroTalk CME, the Node.js process you started with npm start is the signalling server, and the media flows peer to peer between browsers, which is why the project can be free to run and why NAT traversal becomes your problem. The trade is control and cost against operational burden. A team with a single Ubuntu host and modest call volume will find MiroTalk CME cheaper and simpler to reason about. A team that needs calls to work reliably from anywhere, without owning the network edge, is better served by the hosted model, and should treat MiroTalk CME as a prototype rather than a production path.

Editorial conclusion

Adopt MiroTalk CME if you can run a Node.js or Docker service on a public HTTPS host and you want callers to reach named staff through a link rather than an account. Do not adopt it if you cannot terminate TLS yourself, if you need multi-party conferences or call recording, or if AGPL-3.0 does not fit how you ship software. Before you commit, verify three things against your own deployment: that the join and call parameters route callers to the right room, that your reverse proxy passes the WebSocket upgrade to port 8000, and that the host protection password and your .env secrets are set before the instance is reachable from the internet.

Official sources

  1. Issues
  2. License: AGPL-3.0
  3. miroslavpejic85/call-me on GitHub
  4. Project website
  5. README
Community notes

Community notes