Spring Boot backend that:
- Accepts MP4 uploads
- Removes filler words (via whisper.cpp word timestamps)
- Removes long pauses
- Outputs a cleaned MP4
Designed for Render (Basic plan) using:
- FFmpeg for audio extraction + final render
- whisper.cpp (
whisper-cli) for speech-to-text timestamps - PostgreSQL as a job queue (
SKIP LOCKED+ leases) - S3-compatible storage (Cloudflare R2 recommended) for direct uploads/downloads via pre-signed URLs
One codebase / one Docker image, two roles:
- API:
APP_ROLE=api - Worker:
APP_ROLE=worker
POST /v1/jobs
Headers: Idempotency-Key: <uuid>
Optional JSON body:
{
"pauseThresholdMs": 1500,
"paddingMs": 120,
"minKeepSegmentMs": 400,
"fillerWords": ["um","uh","ah","hmm","err"],
"languageHint": "en"
}Response:
{
"jobId": "…",
"uploadUrl": "https://…",
"commitUrl": "/v1/jobs/<jobId>/commit",
"statusUrl": "/v1/jobs/<jobId>"
}Upload the MP4 directly to uploadUrl (HTTP PUT, content-type video/mp4).
POST /v1/jobs/<jobId>/commit → returns 202 Accepted.
GET /v1/jobs/<jobId>
When status=SUCCEEDED, you’ll receive a downloadUrl to the cleaned MP4.
Prereqs:
- Java 17
- PostgreSQL
- An S3-compatible bucket (or use R2)
Run API locally:
cd render-auto-editor
mvn -q -DskipTests package
APP_ROLE=api java -jar target/render-auto-editor-0.1.0.jarRun Worker locally (requires ffmpeg + whisper-cli in PATH):
APP_ROLE=worker java -jar target/render-auto-editor-0.1.0.jarBuild:
docker build -t render-auto-editor:local ./render-auto-editorRun API:
docker run --rm -p 8080:8080 -e APP_ROLE=api render-auto-editor:localRun Worker:
docker run --rm -e APP_ROLE=worker render-auto-editor:localAPP_ROLE:apiorworkerDATABASE_URL(Render Postgres connection string — entrypoint converts it to theJDBC_DATABASE_*vars Spring needs)- Or set
JDBC_DATABASE_URL,JDBC_DATABASE_USERNAME,JDBC_DATABASE_PASSWORDdirectly
- Or set
STORAGE_BUCKET,STORAGE_REGION,STORAGE_ENDPOINT,STORAGE_ACCESS_KEY,STORAGE_SECRET_KEY- If storage is left blank the app will still start; storage-dependent endpoints return
503until configured.
- If storage is left blank the app will still start; storage-dependent endpoints return
Optional:
WHISPER_MODEL_URL,WHISPER_MODEL_PATH
This repo ships a render.yaml that creates the API web service and the Worker background service. The Postgres database is currently commented out in the blueprint so you can verify the deploy works end-to-end first; both services boot in the nodb Spring profile and only expose /healthz.
- In Render → New → Blueprint, point it at this GitHub repo.
- Render reads
render.yamland creates:render-auto-editor-api(web)render-auto-editor-worker(background worker)
- After the first deploy, open each service → Environment and fill the storage secrets:
STORAGE_BUCKET,STORAGE_ENDPOINT,STORAGE_ACCESS_KEY,STORAGE_SECRET_KEY- For Cloudflare R2:
STORAGE_REGION=auto,STORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com - For AWS S3:
STORAGE_REGION=us-east-1(or your region), leaveSTORAGE_ENDPOINTblank
- Trigger a redeploy on both services. The API exposes
/healthz; storage-only endpoints work, but job creation will fail until the database is enabled.
Once you're ready to take the system fully live:
- In
render.yaml, uncomment thedatabases:block and the twoDATABASE_URLenv vars. - Remove the
SPRING_PROFILES_ACTIVE=nodbenv vars on both services. - Commit/push and trigger a redeploy. Render provisions the DB and rewires
DATABASE_URLto both services automatically.