A production-grade multimodal AI system that understands video through combined visual and audio analysis. Upload any video or paste a YouTube/Vimeo/TikTok URL β VELA extracts keyframes, describes them with a vision LLM, transcribes audio with Whisper, and answers natural language questions with timestamped citations.
Video File or URL (YouTube, Vimeo, TikTok, etc.)
β
Frame Extraction Agent β OpenCV scene detection + fallback sampling
β
Vision Description Agent β GPT-4o vision / LLaVA via Ollama (BYOK)
β
Transcript Agent β OpenAI Whisper (runs locally, free)
β
Fusion Agent β Merges visual + audio into timestamped chunks
β
Indexing Agent β Embeds chunks β Qdrant vector DB
β
Retrieval + Synthesis β Semantic search + reranking + LLM answer
β
Streamlit UI β Q&A with frame previews + timestamps
Mac:
brew install ffmpegUbuntu:
sudo apt install ffmpegffmpeg is required for Whisper audio extraction and yt-dlp video merging. Without it, URL processing will fail.
cd vela
pip install -r requirements.txt
pip install yt-dlp # for YouTube/URL supportcp .env.example .env
nano .envMinimum required config:
# For local-only (free, no API key needed):
LLM_PROVIDER=ollama
VISION_PROVIDER=ollama # β use ollama, not openai, unless you have credits
OLLAMA_VISION_MODEL=llava
EMBEDDING_PROVIDER=ollama
# For faster responses (requires paid OpenAI credits):
LLM_PROVIDER=openai
OPENAI_API_KEY=sk-your-key
VISION_PROVIDER=openai
VISION_MODEL=gpt-4oollama pull llava # vision model (describes frames)
ollama pull llama3.2 # text LLM (answers questions)
ollama pull nomic-embed-text # embeddingsOption A β Docker (recommended):
docker compose up -dOption B β Binary (if Docker isn't running):
curl -L https://github.com/qdrant/qdrant/releases/latest/download/qdrant-aarch64-apple-darwin.tar.gz -o qdrant.tar.gz
tar -xzf qdrant.tar.gz
./qdrantLeave this terminal open. Qdrant runs on port 6333.
cd backend
uvicorn main:app --reload --port 8000cd frontend
streamlit run app.pyOpen http://localhost:8501
brew install ffmpeg # Mac
sudo apt install ffmpeg # UbuntuYour OpenAI account has no credits. Switch to local LLaVA:
# In .env:
VISION_PROVIDER=ollama
OLLAMA_VISION_MODEL=llava
# Pull the model:
ollama pull llavaQdrant is not running. Start it:
# Docker:
docker compose up -d
# Or binary:
./qdrantpip install yt-dlpThe backend cached the old config. Restart it:
# Kill the uvicorn process (Ctrl+C) then:
uvicorn main:app --reload --port 8000You're in the wrong folder or the binary wasn't extracted. Re-download:
curl -L https://github.com/qdrant/qdrant/releases/latest/download/qdrant-aarch64-apple-darwin.tar.gz -o qdrant.tar.gz
tar -xzf qdrant.tar.gz
./qdrantCheck your FastAPI backend terminal β the real error is always printed there. Common causes:
- Qdrant not running
- Vision API key invalid
- ffmpeg not installed
- yt-dlp not installed
The OpenAI LLM key has no credits. Switch to Ollama:
# In .env:
LLM_PROVIDER=ollama
OLLAMA_MODEL=llama3.2This is just a warning, not an error. Whisper runs fine on CPU with FP32. Ignore it.
Run through this every time before using VELA:
β‘ Qdrant running on port 6333
β‘ Ollama running (ollama serve)
β‘ llava, llama3.2, nomic-embed-text pulled in Ollama
β‘ ffmpeg installed (ffmpeg -version)
β‘ yt-dlp installed (pip show yt-dlp)
β‘ .env configured with correct VISION_PROVIDER=ollama
β‘ Backend running: uvicorn main:app --reload --port 8000
β‘ Frontend running: streamlit run app.py
# Terminal 1 β Qdrant
./qdrant
# Terminal 2 β Ollama (if not running as a service)
ollama serve
# Terminal 3 β Backend
cd /path/to/vela/backend
uvicorn main:app --reload --port 8000
# Terminal 4 β Frontend
cd /path/to/vela/frontend
streamlit run app.py| Variable | Default | Options | Description |
|---|---|---|---|
LLM_PROVIDER |
ollama |
ollama, openai, anthropic |
Text LLM for answering questions |
VISION_PROVIDER |
ollama |
ollama, openai |
Vision LLM for frame description |
OLLAMA_VISION_MODEL |
llava |
llava, llava-llama3 |
Local vision model |
VISION_MODEL |
gpt-4o |
gpt-4o, gpt-4o-mini |
OpenAI vision model |
WHISPER_MODEL |
base |
tiny, base, small, medium, large |
Transcription quality vs speed |
SCENE_THRESHOLD |
27.0 |
Lower = more frames | Scene detection sensitivity |
MAX_FRAMES_PER_VIDEO |
300 |
Any int | Frame extraction cap |
TOP_K |
10 |
Any int | Chunks retrieved before reranking |
RERANK_TOP_N |
4 |
Any int | Chunks kept after reranking |
After processing a video:
- "What is shown at the 2-minute mark?"
- "Summarize the key points discussed."
- "What diagrams or slides are visible?"
- "At what timestamp does the presenter show the results?"
- "What is written on the whiteboard?"
vela/
βββ backend/
β βββ main.py # FastAPI β /process, /process/url, /query
β βββ config.py # Central config + BYOK routing
β βββ agents/
β β βββ frame_agent.py # Scene detection + keyframe extraction
β β βββ vision_agent.py # Vision LLM frame description
β β βββ transcript_agent.py # Whisper transcription
β β βββ fusion_agent.py # Visual + audio fusion
β β βββ synthesis_agent.py # Timestamped answer generation
β β βββ url_agent.py # yt-dlp YouTube/URL downloader
β βββ graph/
β β βββ orchestrator.py # LangGraph state graph
β βββ rag/
β β βββ embedder.py
β β βββ indexer.py
β β βββ retriever.py
β βββ utils/
β βββ video_utils.py
βββ frontend/
β βββ app.py # Streamlit UI
βββ frames/ # Extracted keyframes (auto-created)
βββ docker-compose.yml
βββ requirements.txt
βββ .env.example
βββ README.md
MIT