⚠️ Note: This project is still under active development and is expected to be completed within a month. Stay tuned for updates!
Note: This is just for development purposes. In production, things would get different.
- Endpoint:
POST /api/recordings - Action:
- Creates a Redis room
- Inserts a new entry in the database
- Returns:
roomId
- Action:
- WebSocket connection is established
- Participant is added to the Redis room participants set
- Action:
- Browser
MediaRecorderbegins recording - Creates 10-second media chunks
- Browser
- Upload Destination:
- Each chunk is uploaded to:
s3://zencast-recordings/{roomId}/{userId}/{chunkIndex}.webm
- Each chunk is uploaded to:
- Endpoint:
POST /api/uploads/complete - Action:
- Triggers processing via Lambda
- Lambda processes all
.webmfiles and generatesfinal.mp4
- Upload Destination:
- Final file is moved to:
s3://zencast-recordings/processed/{roomId}/final.mp4
- Final file is moved to:
zencast/
├── client/ # Frontend application
│ ├── public/ # Static assets
│ ├── src/
│ │ ├── assets/ # Images, fonts, etc.
│ │ ├── components/ # Reusable UI components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── pages/ # Application pages
│ │ ├── services/ # API service calls
│ │ ├── store/ # Redux store
│ │ ├── types/ # TypeScript types
│ │ ├── utils/ # Utility functions
│ │ ├── App.tsx # Main app component
│ │ └── index.tsx # Entry point
│ ├── package.json
│ └── tsconfig.json
│
├── server/ # Backend application
│ ├── config/ # Configuration files
│ ├── controllers/ # Route controllers
│ ├── middleware/ # Express middleware
│ ├── models/ # Database models
│ ├── routes/ # API routes
│ ├── services/ # Business logic
│ ├── utils/ # Utility functions
│ ├── app.js # Express app setup
│ ├── package.json
│ └── server.js # Server entry point
│
├── worker/ # Video processing worker
│ ├── ffmpeg/ # FFmpeg scripts
│ ├── layouts/ # Video layout templates
│ ├── index.js # Worker entry point
│ └── package.json
│
├── shared/ # Shared code between frontend and backend
│ ├── types/ # Shared TypeScript types
│ └── utils/ # Shared utility functions
│
├── .env.example # Environment variables template
├── .gitignore
├── package.json # Root package.json
└── README.md # Project documentation- Browser-based local recording with WebRTC
- Chunked uploads to S3 with resume capability
- Automatic video rendering with dynamic layouts
- Real-time communication between participants
- Frontend: React, TypeScript, TailwindCSS, Redux
- Backend: Node.js, Express, PostgreSQL, Redis
- Real-time: WebRTC, Socket.IO
- Storage: AWS S3
- Video Processing: FFmpeg, Puppeteer
- Clone the repository
- Install dependencies:
npm install - Set up PostgreSQL and Redis
- Configure AWS credentials
- Copy
.env.exampleto.envand fill in values - Run migrations:
npm run migrate - Start services:
- Backend:
npm run start:server - Frontend:
npm run start:client - Worker:
npm run start:worker
- Backend:
npm run dev: Start all services in developmentnpm run build: Build all servicesnpm run test: Run tests
- S3 Bucket for file storage
- IAM User with restricted permissions
- Lambda for video processing (optional)
- EC2 or Elastic Beanstalk for backend
-
Create S3 Bucket:
aws s3api create-bucket --bucket zencast-recordings-UNIQUEID \ --region us-east-1 \ --create-bucket-configuration LocationConstraint=us-east-1
-
Configure CORS:
aws s3api put-bucket-cors --bucket zencast-recordings-UNIQUEID \ --cors-configuration file://cors.json
-
Create IAM Policy:
aws iam create-policy --policy-name ZencastUploadPolicy \ --policy-document file://policy.json
-
Deploy Lambda:
zip -r function.zip . aws lambda create-function --function-name zencast-process-recording \ --zip-file fileb://function.zip \ --handler index.handler \ --runtime nodejs18.x \ --role arn:aws:iam::YOUR_ACCOUNT_ID:role/lambda-role
These variables must be set in your .env files for the frontend and backend services.
# API and WebSocket
VITE_API_BASE_URL=http://localhost:3001
VITE_WS_BASE_URL=ws://localhost:3001
# WebRTC Configuration
VITE_STUN_SERVER_URL=stun:stun.l.google.com:19302
VITE_TURN_SERVER_URL=turn:your.turnserver.com:3478
VITE_TURN_USERNAME=your_turn_username
VITE_TURN_CREDENTIAL=your_turn_password# Server
PORT=3001
# PostgreSQL Database
DATABASE_URL=postgres://username:password@localhost:5432/database_name
# Redis
REDIS_URL=redis://localhost:6379
# AWS S3
AWS_ACCESS_KEY_ID=your_aws_access_key_id
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
AWS_REGION=us-east-1
AWS_S3_BUCKET=your_s3_bucket_name
# JWT Authentication
JWT_SECRET=your_jwt_secret_here
JWT_EXPIRES_IN=1h
REFRESH_TOKEN_EXPIRES_IN=7d- Raw chunks are uploaded to
recordings/{roomId}/{userId}/. - Processed files are saved to
processed/{roomId}/.
To set a lifecycle policy to delete raw chunks after 7 days, run the following command:
aws s3api put-bucket-lifecycle-configuration \
--bucket zencast-recordings-UNIQUEID \
--lifecycle-configuration file://lifecycle.jsonContributions, issues, and feature requests are welcome!
If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.
For any questions or collaboration, reach out at:
📧 [email protected]
🌐 Portfolio | LinkedIn
Made with ❤️ by me

