LiveKit Recording
All your live recording needs in one place.
Record any website using our recorder, or deploy our service to manage it for you.
How it works
The recorder launches Chrome and navigates to the supplied url, grabs audio from pulse and video from a virtual frame buffer, and feeds them into GStreamer.
You can write the output as mp4 to a file or upload it to s3, or forward the output to one or multiple rtmp streams.
Config
Both the standalone recorder and recorder service take a yaml config file. If you will be using templates with your recording requests, ws_url is required, and to record by room name instead of token, api_key and
api_secret are also required. When running in service mode, redis config is required (with the same db as your LiveKit server), as this is how it receives requests.
All config options:
api_key: livekit server api key (required if using templates without supplying tokens)
api_secret: livekit server api secret (required if using templates without supplying tokens)
ws_url: livekit server ws url (required if using templates)
health_port: http port to serve status (optional)
log_level: valid levels are debug, info, warn, error, fatal, or panic. Defaults to debug
redis: (service mode only)
address: redis address, including port
username: redis username (optional)
password: redis password (optional)
db: redis db (optional)
s3: (required if using s3 output)
access_key: s3 access key
secret: s3 access secret
region: s3 region
defaults:
preset: defaults to "NONE", see options below
width: defaults to 1920
height: defaults to 1080
depth: defaults to 24
framerate: defaults to 30
audio_bitrate: defaults to 128 (kbps)
audio_frequency: defaults to 44100 (Hz)
video_bitrate: defaults to 4500 (kbps)
Presets
| Preset |
width |
height |
framerate |
video_bitrate |
| "HD_30" |
1280 |
720 |
30 |
3000 |
| "HD_60" |
1280 |
720 |
60 |
4500 |
| "FULL_HD_30" |
1920 |
1080 |
30 |
4500 |
| "FULL_HD_60" |
1920 |
1080 |
60 |
6000 |
If you don't supply any options with your config defaults or the request, it defaults to FULL_HD_30.
Request
See StartRecordingRequest here.
When using standalone mode, the request can be input as a json file. In service mode, these requests will be made through
the LiveKit server's recording api.
You can input either a url to record from, or choose a template and a layout, and supply either a room_name or token.
We currently have 4 templates available - grid or speaker, each available in light or dark.
Your config will need your server api key and secret, along with the websocket url.
Check out our web README to learn more or create your own.
Output
You can either output to a file, upload to an s3_url, or write to one or more rtmp urls.
Options
You can also override any defaults set in your config.yaml.
All request options:
{
"url": "<your-recording-domain.com>",
"template": {
"layout": "<grid|speaker>-<light|dark>",
"room_name": "<room-to-record>",
"token": "<token>"
},
"file": "/out/recording.mp4",
"s3_url": "bucket/path/filename.mp4",
"rtmp": {
"urls": ["<rtmp://stream-url.com>"]
},
"options": {
"preset": "FULL_HD_60",
"width": 1920,
"height": 1080,
"depth": 24,
"framerate": 60,
"audio_bitrate": 128,
"audio_frequency": 44100,
"video_bitrate": 6000
}
}
Service Mode
Simply deploy the service, and submit requests through your LiveKit server.
How it works
The service listens to a redis subscription and waits for the LiveKit server to make a reservation. Once the reservation
is made to ensure availability, the service waits for a StartRecording request from the server before launching the recorder.
The recorder will be stopped by either a END_RECORDING signal from the server, or automatically when the last participant leaves if using our templates.
A single service instance can record one room at a time.
Deployment
See guides and deployment docs at https://docs.livekit.io/guides/recording
Running locally
If you want to try running against a local livekit server, you'll need to make a couple changes:
- open
/usr/local/etc/redis.conf and comment out the line that says bind 127.0.0.1
- change
protected-mode yes to protected-mode no in the same file
- add
--network host to your docker run command
- update your redis address from
localhost to your host ip as docker sees it:
- on linux, this should be
172.17.0.1
- on mac or windows, run
docker run -it --rm alpine nslookup host.docker.internal and you should see something like
Name: host.docker.internal Address: 192.168.65.2
These changes allow the service to connect to your local redis instance from inside the docker container.
Finally, to build and run:
docker build -t livekit-recorder .
docker run --network host \
-e SERVICE_MODE=1 \
-e LIVEKIT_RECORDER_CONFIG="$(cat config.yaml)" \
livekit-recorder
You can then use our cli to submit recording requests to your server.
Examples
Start by filling in a config.yaml:
api_key: <livekit-server-api-key>
api_secret: <livekit-server-api-secret>
ws_url: <livekit-server-ws-url>
s3:
access_key: <s3-access-key>
secret: <s3-secret>
region: <s3-region>
Basic recording
basic.json:
{
"template": {
"layout": "speaker-dark",
"room_name": "my-room"
},
"file": "/out/demo.mp4"
}
mkdir -p ~/livekit/output
docker run --rm \
-e LIVEKIT_RECORDER_CONFIG="$(cat config.yaml)" \
-e RECORDING_REQUEST="$(cat basic.json)" \
-v ~/livekit/recordings:/out \
livekit/livekit-recorder
Record at 720p, with 2048kbps video bitrate, and upload result to s3
s3.json:
{
"url": "https://www.youtube.com/watch?v=BHACKCNDMW8",
"s3_url": "bucket/path/filename.mp4",
"options": {
"width": "1280",
"height": "720",
"video_bitrate": 2048
}
}
docker run --name my-recorder --rm \
-e LIVEKIT_RECORDER_CONFIG="$(cat config.yaml)" \
-e RECORDING_REQUEST="$(cat s3.json)" \
livekit/livekit-recorder
docker stop my-recorder
Stream to Twitch at 1080p, 60fps
twitch.json:
{
"template": {
"layout": "speaker-dark",
"token": "<recording-token>"
},
"rtmp": {
"urls": ["rtmp://live.twitch.tv/app/<stream-key>"]
},
"options": {
"preset": "FULL_HD_60"
}
}
docker run --rm \
-e LIVEKIT_RECORDER_CONFIG="$(cat config.yaml)" \
-e RECORDING_REQUEST="$(cat twitch.json)" \
livekit/livekit-recorder
Ending a recording
Once started, there are a number of ways to end the recording:
docker stop <container>
- if using our templates, the recorder will stop automatically when the last participant leaves
- if using your own webpage, logging
END_RECORDING to the console
With any of these methods, the recorder will stop gstreamer and finish uploading before shutting down.