This is a customized fork of the open-source repository attendee by Noah Duncan, optimized to work with our specific architecture.
The Meeting Recorder is a Django application designed to run as a single Docker image, supported by Postgres and Redis.
Core Architecture:
- Main API: Handles authentication, account management, and bot orchestration.
- Bots: The API spins up recorder pods (workers) called "Bots". These bots:
- Join a meeting (Zoom, Teams, etc.).
- Record the audio/video.
- Upload the raw data to Object Storage (OpenStack Swift).
- Leave the meeting and destroy themselves.
- Trigger a callback to the
transcript-gateway.
This fork deviates from the original attendee repository in several key ways:
- Custom Storage: We utilize OpenStack Swift (via Infomaniak) instead of AWS S3.
- Location:
/bots/storage/infomaniak_storage.py
- Location:
- Callbacks: Post-recording, the bot triggers a callback to our
transcript-gateway.- Location:
/transcript_services/v1/api_service.py
- Location:
- Kubernetes Native: We have removed non-essential bloat and added more logs to support running inside a K8s cluster.
Best for quick logic changes and database testing.
- Build the image:
docker compose -f dev.docker-compose.yml build - Generate Environment Variables:
docker compose -f dev.docker-compose.yml run --rm recorder-api python init_env.py > .env(Edit the generated.envfile to add your AWS/Storage credentials) - Start Services:
docker compose -f dev.docker-compose.yml up - Run Migrations:
docker compose -f dev.docker-compose.yml exec recorder-api python manage.py migrate - Create Account:
- Go to
localhost:8001to sign up. - Find the confirmation link in your terminal logs (e.g.,
http://localhost:8001/accounts/confirm-email/<key>/). - Login to obtain your API Key.
- Go to
Best for testing integration with the wider cluster architecture.
Prerequisites:
skaffold(brew install skaffold)- Docker Desktop (Kubernetes enabled)
- Clone of the
transcript-gitopsrepository (for manifests).
Configuration:
- Update
skaffold.yamlto point to your local path for the manifests:manifests: rawYaml: - /Users/USERNAME/PATH_TO/transcript-k8s/deployment-meeting-recorder-api-dev.yaml
- Secrets Management:
- Copy examples:
cp ./secret-examples/secret-docker.yaml secret-docker.yaml - Apply:
kubectl apply -f secret-docker.yaml(and repeat forsecret-transcript.yaml)
- Copy examples:
- Apply Configs & Deps:
kubectl apply -f configmap-transcript.yamlkubectl apply -f deployment-redis.yamlkubectl apply -f deployment-postgres.yamlkubectl apply -f role-meeting-recorder-bot.yaml
- Run:
skaffold dev
- Create Migrations:
docker compose -f dev.docker-compose.yml exec recorder-api python manage.py makemigrations bots - Apply Migrations:
docker compose -f dev.docker-compose.yml exec recorder-api python manage.py migrate
- Build the Docker image (Takes about 5 minutes)
docker build --platform=linux/amd64 -t azytaku/transcript-meeting-recorder:1.0.33 -f Dockerfile.dev .- Push the image to Docker Hub
docker push azytaku/transcript-meeting-recorder:1.0.33Join a meeting with a POST request to /bots:
curl -X POST http://localhost:8000/api/v1/bots \
-H 'Authorization: Token <YOUR_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"meeting_url": "https://us05web.zoom.us/j/84315220467?pwd=9M1SQg2Pu2l0cB078uz6AHeWelSK19.1", "bot_name": "My Bot"}'
Response:
{"id":"bot_3hfP0PXEsNinIZmh","meeting_url":"https://us05web.zoom.us/j/4849920355?pwd=aTBpNz760UTEBwUT2mQFtdXbl3SS3i.1","state":"joining","transcription_state":"not_started"}
The API will respond with an object that represents your bot's state in the meeting.
Make a GET request to /bots/<id> to poll the bot:
curl -X GET http://localhost:8000/api/v1/bots/bot_3hfP0PXEsNinIZmh \
-H 'Authorization: Token <YOUR_API_KEY>' \
-H 'Content-Type: application/json'
Response:
{"id":"bot_3hfP0PXEsNinIZmh","meeting_url":"https://us05web.zoom.us/j/88669088234?pwd=AheaMumvS4qxh6UuDtSOYTpnQ1ZbAS.1","state":"ended","transcription_state":"complete"}
When the endpoint returns a state of ended, it means the meeting has ended. When the transcription_state is complete it means the meeting recording has been transcribed.
Once the meeting has ended and the transcript is ready make a GET request to /bots/<id>/transcript to retrieve the meeting transcripts:
curl -X GET http://localhost:8000/api/v1/bots/bot_3hfP0PXEsNinIZmh/transcript \
-H 'Authorization: Token mpc67dedUlzEDXfNGZKyC30t6cA11TYh' \
-H 'Content-Type: application/json'
Response:
[{
"speaker_name":"Alan Turing",
"speaker_uuid":"16778240","speaker_user_uuid":"AAB6E21A-6B36-EA95-58EC-5AF42CD48AF8",
"timestamp_ms":1079,"duration_ms":7710,
"transcription":"You can totally record this, buddy. You can totally record this. Go for it, man."
},...]
You can also query this endpoint while the meeting is happening to retrieve partial transcripts.