Jump instantly to the scenes you want by asking AI questions
VideoQ is an AI-powered video navigator that automatically transcribes videos and lets you chat with them in natural language.
Japanese version: README.ja.md
API integration supported - Connect VideoQ with existing systems through API key authentication and an OpenAI-compatible API. See Developer API Integration for details.
Design documentation - See docs/ for architecture diagrams, ER diagrams, sequence diagrams, and other technical details.
- Upload supported video formats - MP4, MOV, AVI, MKV, WebM, M4V, MPEG, 3GP, and more
- Ask questions - For example, "What did they say about the budget?" or "Summarize the key points"
- Search video content - Find specific moments without scrubbing through hours of footage
- Organize with tags - Manage videos with custom tags and colors
- Share insights - Create shareable video groups for team collaboration
- Multilingual UI - Switch between Japanese and English interfaces
- Docker and Docker Compose installed
- An OpenAI API key for the default configuration
- A SearchAPI API key if you want to import YouTube videos
This guide walks you through starting VideoQ locally and opening it in your browser.
- Go to OpenAI Platform
- Sign up or log in
- Click "Create new secret key"
- Copy the key, which starts with
sk-...
The default setup uses OpenAI for transcription, embeddings, and chat. If you want a fully local setup, switch to the local Whisper / Ollama configuration described below.
# Clone the project and enter the directory
git clone https://github.com/yukiharada1228/videoq.git
cd videoq
# Copy the environment file
cp .env.example .envOpen .env and set the OpenAI API key used by the default configuration.
OPENAI_API_KEY=sk-proj-...If you want to fetch subtitles from YouTube URLs, each user should configure their own SearchAPI key from the VideoQ Settings screen.
# Start all services. The first run may take a few minutes.
docker compose up --build -d
# Initial setup
docker compose exec backend python manage.py migrate
docker compose exec backend python manage.py collectstatic --noinput
docker compose exec backend python manage.py createsuperuserOpen http://localhost in your browser.
Useful links:
- Admin panel: http://localhost/api/admin for managing users and videos
- API docs: http://localhost/api/docs/ for developers
First steps:
- Log in with the admin account you created
- Create regular users if needed
- Configure upload limits for regular users
- Upload a video, wait for transcription, and try chatting with it
VideoQ manages per-user limits directly from the admin panel.
Where to configure them
- Open the admin panel
- Open
Users - Select the target user
- Configure the following values and save
| Setting | Description |
|---|---|
Max video upload size mb |
Maximum upload size per video in MB. Default: 500 |
Storage limit gb |
Storage limit in GB. Default: 0, or leave blank for unlimited |
Processing limit minutes |
Monthly transcription processing limit in minutes. Default: 0, or leave blank for unlimited |
Ai answers limit |
Monthly AI answer limit. Default: 0, or leave blank for unlimited |
Optional: cloud storage setup (AWS S3 / Cloudflare R2)
This step is optional. VideoQ stores videos on the local filesystem by default, but you can also use object storage such as AWS S3 or Cloudflare R2.
Configure the following values in .env:
USE_S3_STORAGE=true
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_STORAGE_BUCKET_NAME=your-bucket
# AWS S3
AWS_S3_REGION_NAME=ap-northeast-1
# Cloudflare R2
AWS_S3_ENDPOINT_URL=https://<account-id>.r2.cloudflarestorage.com
AWS_S3_REGION_NAME=autoRestart the services:
docker compose restart backend celery-workerOptional: reduce costs with local AI
This step is optional. Skip it if the default OpenAI setup works for you.
If you want to reduce costs or run fully offline for privacy reasons, you can switch to free local AI models with the following steps.
Local Whisper for free transcription
Use your computer's GPU for faster, free transcription.
Quick setup:
# 1. Fetch whisper.cpp from the VideoQ root directory
git submodule update --init --recursive
cd whisper.cpp
# 2. Build
cmake -B build
cmake --build build -j --config Release
# 3. Download a model
bash ./models/download-ggml-model.sh large-v3-turbo
# 4. Start the server
./build/bin/whisper-server -m models/ggml-large-v3-turbo.bin --inference-path /audio/transcriptions -l jaConfigure VideoQ:
Edit .env:
WHISPER_BACKEND=whisper.cpp
WHISPER_LOCAL_URL=http://host.docker.internal:8080Restart the services:
docker compose restart backend celery-workerLocal AI chat with Ollama as a free ChatGPT alternative
Install Ollama:
- Download it from ollama.com
- Install and run it
Pull a model:
ollama pull qwen3:0.6bConfigure VideoQ:
Edit .env:
LLM_PROVIDER=ollama
LLM_MODEL=qwen3:0.6b
OLLAMA_BASE_URL=http://host.docker.internal:11434Restart the services:
docker compose restart backend celery-workerLocal embeddings for free text search
Pull an embedding model:
ollama pull qwen3-embedding:0.6bConfigure VideoQ:
Edit .env:
EMBEDDING_PROVIDER=ollama
EMBEDDING_MODEL=qwen3-embedding:0.6b
OLLAMA_BASE_URL=http://host.docker.internal:11434Restart the services:
docker compose restart backend celery-workerImportant: If you switch from OpenAI embeddings to local embeddings, you must re-index existing videos from the admin panel.
The default Docker Compose stack uses Caddy as its public gateway. Local development remains HTTP by default. Set a production DNS name to enable automatic Let's Encrypt certificate issuance, HTTP-to-HTTPS redirects, and certificate renewal; no Certbot container or renewal cron is required.
- Point the A/AAAA record for a stable domain (for example,
videoq.example.com) to the server's public IP address. - Allow inbound TCP ports 80 and 443. UDP 443 is optional and enables HTTP/3.
- Configure the production values in
.env:
SITE_ADDRESS=videoq.example.com
DJANGO_ENV=production
ALLOWED_HOSTS=videoq.example.com
CORS_ALLOWED_ORIGINS=https://videoq.example.com
FRONTEND_URL=https://videoq.example.com
SECRET_KEY=<a-long-random-value>- Start the stack:
docker compose up -d --buildOnce DNS is active and ports 80/443 are externally reachable, Caddy obtains and renews the certificate automatically. Open https://videoq.example.com to confirm that the application is available over HTTPS.
Keeping the same DNS name means a later server or cloud migration only requires a DNS change. The public application URL can remain unchanged.
VideoQ supports API key authentication for integrations, so you can use it from existing systems and batch jobs through server-to-server communication.
Issue a vq_... integration key from "Integration API Keys" in the Settings screen. Use the X-API-Key header for the REST API and Authorization: Bearer <vq_...> for the OpenAI-compatible API. For integration steps, authentication details, and endpoint-specific sample code in cURL / JavaScript / TypeScript / Python / Go / Java / C# / PHP / Ruby, see the in-app developer docs.
- Developer docs: http://localhost/docs
- OpenAPI (Swagger UI): http://localhost/api/docs/
- ReDoc: http://localhost/api/redoc/
VideoQ exposes a built-in analytics-only remote MCP server at POST /api/mcp/. Any MCP client that speaks Streamable HTTP โ Claude Code, Cursor, and any client that can launch mcp-remote โ can connect with just a URL and an API key. No local process to install.
๐ก๏ธ Design policy: Sending RAG chat questions is intentionally excluded. MCP access is limited to reading and analyzing existing data.
| Tool | Purpose |
|---|---|
list_videos / get_video |
List videos and view details (including transcripts) |
list_groups / get_group |
List groups and their member videos |
list_tags |
List tags |
get_chat_history |
Chat history for a group (with feedback) |
get_chat_analytics |
Question counts, period, daily time series, feedback aggregates |
get_chat_analytics_keywords |
Keyword frequency in questions |
get_evaluation_summary |
RAGAS average scores (faithfulness / answer_relevancy / context_precision) |
list_evaluation_logs |
Per-log RAGAS scores |
List tools support limit / offset pagination (default 20, maximum 100).
Log in to VideoQ and issue a vq_... key from Settings โ Integration API Keys, then copy it.
The endpoint URL is your VideoQ host followed by /api/mcp/ โ for example, http://localhost/api/mcp/ for a local Docker setup or https://your-domain.example.com/api/mcp/ in production. Authenticate with Authorization: Bearer vq_... (or the equivalent X-API-Key header).
For Claude Code:
claude mcp add --transport http videoq https://your-domain.example.com/api/mcp/ \
--header "Authorization: Bearer vq_xxxxxxxxxxxxxxxx"For Claude Desktop / claude.ai (built-in connector, OAuth 2.1), paste just the MCP URL into Settings โ Connectors โ Add custom connector and approve the consent screen. No API key needed โ VideoQ implements OAuth 2.1 + Dynamic Client Registration (RFC 7591) per the MCP Authorization spec.
https://your-domain.example.com/api/mcp/
Behind the scenes the client discovers the authorization server via /.well-known/oauth-protected-resource/api/mcp and /.well-known/oauth-authorization-server, registers itself dynamically at /api/oauth/register/, and runs the standard authorization-code flow with PKCE. You can revoke any granted token at any time from Settings โ Connected Apps.
For a self-hosted production instance, first complete the Docker Compose HTTPS deployment. The OAuth issuer must match the public HTTPS origin, so set it in .env and apply the change to the backend:
OAUTH2_PROVIDER_ISSUER_URL=https://videoq.example.comdocker compose up -d backendThen confirm that the MCP endpoint and OAuth metadata are publicly available before registering the connector:
https://videoq.example.com/api/mcp/
https://videoq.example.com/.well-known/oauth-authorization-server
https://videoq.example.com/.well-known/oauth-protected-resource/api/mcp
If you need to fall back to the mcp-remote bridge for an older client, configure it with your API key instead:
{
"mcpServers": {
"videoq": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-domain.example.com/api/mcp/",
"--header",
"Authorization: Bearer vq_xxxxxxxxxxxxxxxx"
]
}
}
}Config file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Cursor and other Streamable HTTP-capable clients use the same URL + header pattern.
Restart the client and confirm that the MCP server appears as videoq. Try prompts like "Show the RAGAS evaluation summary for group 1" or "What keywords have come up in recent questions?" to trigger the matching tools.
401 Unauthorizedโ The API key (or OAuth token) is missing, malformed, or revoked. Reissue from Settings and update the header, or re-approve the OAuth connector.404 Not Foundโ The URL is wrong. Confirm the host and the/api/mcp/path (trailing slash is optional).- OAuth connector cannot discover the server โ Confirm that
https://<host>/.well-known/oauth-authorization-serverandhttps://<host>/.well-known/oauth-protected-resource/api/mcpreturn JSON. These paths must be served by the API host at the root (not under/api/), so nginx / reverse proxies must forward/.well-known/oauth-*to the backend.
Found a bug or want to add a feature? Contributions are welcome.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests as needed
- Submit a pull request
- ่คๅ ๅผไบ. "AIใจๅ ฑใซ็ใใๆไปฃใซใใใๆ่ฒใธใฎ็ๆ AI ๆดป็จ๏ผใ่คๅ AIๅ ็ใ". ๆ ๅ ฑๅฆ็ๅญฆไผ ไผ่ชใๆ ๅ ฑๅฆ็ใ Vol.66, No.11 (2025).
See the LICENSE file for details.
