Table of Contents
A video recognition system that works like Shazam — but for video. It analyzes short snippets (2–5 seconds), breaks them into keyframes, and uses perceptual hashing to identify the exact or near-exact source, even if the clip has been edited or altered. This preserves the full context of the snippet and enables reliable tracking of original video content.
Key features:
- Upload full video snippets, not just images — automatic extraction of keyframes for context-aware matching.
- Accurate source identification via perceptual hashing tolerant to modifications.
- Optimized for quick, precise matching of short video fragments.
- Scalable microservices architecture built to handle heavy traffic without performance loss.
Turron is structured into 6 microservices, each with bounded responsibilities:
-
Eureka Server: Manages service discovery using Netflix Eureka with
@DiscoveryClient. -
Upload Service: Accepts short videos via REST API, stores them in MinIO, and sends processing tasks to Kafka.
- Frame Extraction Service: Extracts 5-10 keyframes from videos using FFmpeg, normalizes orientation for robustness, and forwards frames to Kafka for hashing.
...
- Hashing Service: Computes pHashes for keyframes and stores it in database.
...
- Search Service: Matches snippet videos to source videos using perceptual hash comparisons with sliding-window Hamming distance, storing results in database.
- API Gateway: Centralized REST API endpoint managing requests, authentication, and response aggregation.
- Clone the repository:
git clone https://github.com/fl1s/turron.git
- Navigate to the project directory:
cd turron - Create .env.dev file from the .env.example:
bash / zsh / powerShell
cd .config/secretscmdcp .env.example .env.dev
copy .env.example .env.dev - Start the dev environment with Docker Compose:
docker-compose --env-file .config/secrets/.env.dev up
- Verify services are running:
docker ps
- Go to the API Endpoints
Set up Turron locally using Docker Compose for the dev environment or deploy to Kubernetes for production.
Ensure you have the following installed:
- Java 21
- Gradle
- Docker and Docker Compose
- kubectl (for prod environment)
- PostgreSQL, Kafka, MinIO (or use Docker Compose)
java --version gradle --version docker --version
- Clone the repository:
git clone https://github.com/fl1s/turron.git
- Navigate to the project directory:
cd turron - Build all microservices with Gradle:
cd microservice-name ./gradlew clean build - Start the dev environment with Docker Compose:
docker-compose up -d
- Verify services are running:
docker ps
POST {{api-gateway}}/api/v1/upload/snippet
Form Data:
| Field | Description | Type |
|---|---|---|
| file | MP4 video file | file (mp4) |
Response:
{
"snippetId": "..."
}POST {{api-gateway}}/api/v1/upload/source
Form Data:
| Field | Description | Type |
|---|---|---|
| file | MP4 video file | file (mp4) |
Response:
{
"sourceId": "..."
}GET {{api-gateway}}/api/v1/search/best-match/:snippetId
Path Parameter:
| Parameter | Description | Type |
|---|---|---|
| snippetId | Snippet video ID | string |
Response:
{
"downloadUrl": "..."
}This project uses GitHub Actions.
The .github/workflows/build.yml workflow runs on every push and pull request to the main branch. It performs the following steps:
- Checks out the repository
- Sets up Java 21 using the Temurin distribution
- Caches Gradle dependencies to speed up builds
- Builds each service defined in the job matrix:
eureka-serverupload-serviceextraction-servicehashing-servicesearch-serviceapi-gateway
- Authenticates to GitHub Container Registry (GHCR)
- Builds and pushes Docker images using a composite action located at
.github/actions/docker-build-push
Each Docker image is tagged with:
latest- a short Git commit SHA
- a date-based tag in
YYYYMMDDformat
Our project includes out-of-the-box monitoring setup using Prometheus and Grafana.
- Each microservice exposes metrics via Spring Boot Actuator on the
/actuator/prometheusendpoint. - Prometheus scrapes these endpoints regularly to collect metrics.
- Grafana connects to Prometheus as a data source to visualize metrics on dashboards.
Prometheus config is located at:
monitoring/prometheus/prometheus.yml
monitoring/prometheus/— Prometheus config filesmonitoring/grafana/— Grafana dashboards and config files
- Start Prometheus using the config from
monitoring/prometheus/prometheus.yml(it's already configured in docker-compose). - Start Grafana and add Prometheus as a data source (
http://localhost:9090). - Create your dashboards in Grafana or import community dashboards for Spring Boot metrics.
- Access your dashboards to monitor service health, performance, and custom metrics.
- In Zero Trust you need to go to
Network -> Tunnels, then create a new tunnel with the name of your domain. - Get the token and put its value in the field
CLOUDFLARED_TUNNEL_TOKENin.config/secrets/.env.prod. - In
published application routes, set root route tonginx:80. - Also, don't forget to set the minio subdomain (s3.yourdomain) and route to
nginx:80. - In
Additional application settings -> HTTP settingssetHTTP Host headervalueminio:9000 - In
.config/nginx/nginx.confchangeserver_nameto your domain and subdomain.
Contributions are welcome to enhance Turron! Follow these steps:
- Fork the Project.
- Create your Feature Branch:
git checkout -b feature/fuzz-buzz-creature
- Commit your Changes:
git commit -m 'feat: add some fuzzBuzzCreatureFeature' - Push to the Branch:
git push --set-upstream origin feature/fuzz-buzz-creature
- Open a Pull Request.
Read our Contributing Guidelines for more details(I also do it later).
Distributed under the Apache 2.0 License. See LICENSE for more information.
fl1s - GitHub
Project Link: https://github.com/fl1s/turron
