SkillAgentSearch skills...

Zoomrec

Record Zoom meetings automatically in headless docker container with Python and FFmpeg

Install / Use

/learn @kastldratza/Zoomrec

README

<h1 align="center"> zoomrec </h1> <h4 align="center"> A all-in-one solution to automatically join and record Zoom meetings. </h4> <p align="center"> <a href="https://github.com/kastldratza/zoomrec/actions/workflows/docker-publish.yml"><img src="https://github.com/kastldratza/zoomrec/actions/workflows/docker-publish.yml/badge.svg" alt="GitHub Workflow Status"></a> <a href="https://github.com/kastldratza/zoomrec/actions/workflows/codeql.yml"><img src="https://github.com/kastldratza/zoomrec/actions/workflows/codeql.yml/badge.svg" alt="GitHub Workflow Status"></a> <a href="https://github.com/kastldratza/zoomrec/actions/workflows/snyk.yml"><img src="https://github.com/kastldratza/zoomrec/actions/workflows/snyk.yml/badge.svg" alt="GitHub Workflow Status"></a> <a href="https://github.com/kastldratza/zoomrec/actions/workflows/snyk-container-analysis.yml"><img src="https://github.com/kastldratza/zoomrec/actions/workflows/snyk-container-analysis.yml/badge.svg" alt="GitHub Workflow Status"></a> <br> <img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/kastldratza/zoomrec"> <img alt="Docker Image Size (tag)" src="https://img.shields.io/docker/image-size/kastldratza/zoomrec/latest"> <img alt="Github Stars" src="https://img.shields.io/github/stars/kastldratza/zoomrec.svg"> </p>

Meeting Recording API

If you’re looking for a hosted Meeting Recording API, consider checking out Recall.ai, an API that works with Zoom, Google Meet, Microsoft Teams, In-person meetings, and more.


  • Python3 - Script to automatically join Zoom meetings and control FFmpeg
  • FFmpeg - Triggered by python script to start/stop screen recording
  • Docker - Headless VNC Container based on Ubuntu 20.04 with Xfce window manager and TigerVNC
  • Telegram - Get notified about your recordings

Join with ID and Passcode | Join with URL :-------------------------:|:-------------------------: |


Installation

The entire mechanism runs in a Docker container. So all you need to do is install Docker and use the image from Registry.

Requirements

Docker Registry

Docker images are build and pushed automatically to Docker Hub and GitHub Container Registry.

So you can choose and use one of them:

  • ghcr.io/kastldratza/zoomrec:master
  • kastldratza/zoomrec:latest

For my examples in this README I used kastldratza/zoomrec:latest


Usage

  • Container saves recordings at /home/zoomrec/recordings
  • The current directory is used to mount recordings-Folder, but can be changed if needed
    • Please check use of paths on different operating systems!
    • Please check permissions for used directory!
  • Container stops when Python script is terminated
  • Zoomrec uses a CSV file with entries of Zoom meetings to record them
    • The csv can be passed as seen below (mount as volume or add to docker image)
  • To "say" something after joining a meeting:
    • paplay (pulseaudio-utils) is used to play a sound to a specified microphone output, which is mapped to a microphone input at startup.
    • paplay is triggered and plays a random file from /home/zoomrec/audio
    • Nothing will be played if directory:
      • does not contain .wav files
      • is not mounted properly

CSV structure

CSV must be formatted as in example/meetings.csv

  • Delimiter must be a semicolon ";"
  • Only meetings with flag "record = true" are joined and recorded
  • "description" is used for filename when recording
  • "duration" in minutes (+5 minutes to the end)

weekday | time | duration | id | password | description | record -------- | -------- | -------- | -------- | -------- | -------- | -------- monday | 09:55 | 60 | 111111111111 | 741699 | Important_Meeting | true monday | 14:00 | 90 | 222222222222 | 321523 | Unimportant_Meeting | false tuesday| 17:00 | 90 | https://zoom.us/j/123456789?pwd=abc || Meeting_with_URL | true

VNC

You can connect to zoomrec via vnc and see what is happening.

Connect (default)

Hostname | Port | Password -------- | -------- | -------- localhost | 5901 | zoomrec

Telegram

Zoomrec can notify you via Telegram about starting and ending a recording or if joining a meeting failed. All you need is a bot token and a chat id of a Telegram channel.

At first create a new telegram bot to get the bot token. After that create a new channel and add the bot with sufficient permissions to write messages in that channel. Finally get the chat id of your channel and look below how to pass your Telegram details to Zoomrec.

Preparation

To have access to the recordings, a volume is mounted, so you need to create a folder that container users can access.

[ IMPORTANT ]

Create folders and set permissions (on Host)

mkdir -p recordings/screenshots
chown -R 1000:1000 recordings

mkdir -p audio
chown -R 1000:1000 audio

Flags

Set timezone (default: Europe/Berlin)

docker run -d --restart unless-stopped \
  -e TZ=Europe/Berlin \
  -v $(pwd)/recordings:/home/zoomrec/recordings \
  -v $(pwd)/example/audio:/home/zoomrec/audio \
  -v $(pwd)/example/meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Set debugging flag (default: False)

  • screenshot on error
  • record joining
  • do not exit container on error
docker run -d --restart unless-stopped \
  -e DEBUG=True \
  -v $(pwd)/recordings:/home/zoomrec/recordings \
  -v $(pwd)/example/audio:/home/zoomrec/audio \
  -v $(pwd)/example/meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Set Telegram details

docker run -d --restart unless-stopped \
  -e TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN" \
  -e TELEGRAM_CHAT_ID="-100_YOUR_CHAT_ID" \
  -v $(pwd)/recordings:/home/zoomrec/recordings \
  -v $(pwd)/example/audio:/home/zoomrec/audio \
  -v $(pwd)/example/meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Set Zoom display name

docker run -d --restart unless-stopped \
  -e DISPLAY_NAME="zoomrec" \
  -v $(pwd)/recordings:/home/zoomrec/recordings \
  -v $(pwd)/example/audio:/home/zoomrec/audio \
  -v $(pwd)/example/meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Windows / cmd

docker run -d --restart unless-stopped \
  -v %cd%\recordings:/home/zoomrec/recordings \
  -v %cd%\example\audio:/home/zoomrec/audio \
  -v %cd%\example\meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Windows / PowerShell

docker run -d --restart unless-stopped `
  -v ${PWD}/recordings:/home/zoomrec/recordings `
  -v ${PWD}/example/audio:/home/zoomrec/audio `
  -v ${PWD}/example/meetings.csv:/home/zoomrec/meetings.csv:ro `
  -p 5901:5901 `
  --security-opt seccomp:unconfined `
kastldratza/zoomrec:latest

Linux / macOS

docker run -d --restart unless-stopped \
  -v $(pwd)/recordings:/home/zoomrec/recordings \
  -v $(pwd)/example/audio:/home/zoomrec/audio \
  -v $(pwd)/example/meetings.csv:/home/zoomrec/meetings.csv:ro \
  -p 5901:5901 \
  --security-opt seccomp:unconfined \
kastldratza/zoomrec:latest

Customization example

Add meetings.csv to image

# Switch to example directory
cd example

# Build new image by customized Dockerfile
docker build -t kastldratza/zoomrec-custom:latest .

# Run image without mounting meetings.csv and audio directory
# Linux
docker run -d --restart unless-stopped -v $(pwd)/recordings:/home/zoomrec/recordings -p 5901:5901 --security-opt seccomp:unconfined kastldratza/zoomrec-custom:latest

# Windows / PowerShell
docker run -d --restart unless-stopped -v ${PWD}/recordings:/home/zoomrec/recordings -p 5901:5901 --security-opt seccomp:unconfined kastldratza/zoomrec-custom:latest

# Windows / cmd
docker run -d --restart unless-stopped -v %cd%\recordings:/home/zoomrec/recordings -p 5901:5901 --security-opt seccomp:unconfined kastldratza/zoomrec-custom:latest

Supported actions

  • [x] Show when the next meeting starts
  • [x] Join a Meeting from csv with id and password
  • [x] Wrong error: Invalid meeting ID / Leave
  • [x] Join with Computer Audio
  • [x] Please wait for the host to start this meeting.
  • [x] Please wait, the meeting host will let you in soon.
  • [x] Enter Full Screen
  • [x] Switch to Speaker View
  • [x] Continuously check: This meeting is being recorded / Continue
  • [x] Continuously check: Hide Video Panel
  • [x] Continuously check: This meeting has been ended by host
  • [x] Quit ffmpeg gracefully on abort
  • [x] Host is sharing poll results
  • [x] This meeting is for authorized attendees only / Leave meeting
  • [x] Play sound after joining a meeting
  • [x] Join a Meeting from csv with url

Roadmap

  • [ ] Refactoring
  • [ ] Create terraform stack to deploy in AWS
  • [ ] Join a Meeting from calendar
  • [ ] Sign In to existing Zoom account
  • [ ] Join Breakout Room
  • [ ] Support to record Google Meet, MS Teams, Cisco WebEx calls too
  • [ ] Ability to monitor recordings sessions in various containers

Testing

Create unittests for different use cases:

  • [ ] Join meeting
  • [ ] Start / Stop ffmpeg and check if
View on GitHub
GitHub Stars313
CategoryDevelopment
Updated5d ago
Forks78

Languages

Python

Security Score

100/100

Audited on Mar 24, 2026

No findings