The Yiku Thumbnail Generator service is a Node.js application that generates thumbnails from video files stored in Google Cloud Storage and uploads them to Cloudflare R2 storage. It also updates the Supabase database with thumbnail URLs.
http://localhost:3000
The service requires proper configuration of environment variables for:
- Google Cloud Platform (GCP) service account credentials
- Cloudflare R2 storage credentials
- Supabase database credentials
GET /health
Checks the overall health status of the service including disk usage, GCP authentication, and R2 connection.
Response:
{
"status": "healthy",
"diskUsage": "45%",
"gcpAuth": true,
"r2Auth": true,
"timestamp": "2025-08-10T17:30:00.000Z"
}POST /generate
Generates a thumbnail from a video file and uploads it to R2 storage.
Request Body:
{
"video_url": "gs://bucket-name/videos/video-id/video.mp4",
"video_id": "video-id"
}Response (Success):
{
"success": true,
"thumbnailUrl": "https://cdn.yiku.studio/thumbnails/video-id.jpg",
"videoId": "video-id"
}Response (Error):
{
"success": false,
"error": "Error message",
"videoId": "video-id"
}Process Flow:
- Downloads video from Google Cloud Storage
- Generates thumbnail using FFmpeg (400x600px with padding)
- Uploads thumbnail to R2 storage
- Updates Supabase database with thumbnail URL
- Cleans up temporary files
GET /status
Provides detailed status information about the service.
Response:
{
"diskUsage": "45%",
"tempVideos": 2,
"tempThumbnails": 1,
"gcpAuth": true,
"r2Auth": true,
"timestamp": "2025-08-10T17:30:00.000Z"
}POST /cleanup
Manually triggers cleanup of old temporary files (files older than 30 minutes).
Response:
{
"success": true,
"message": "Cleanup completed"
}POST /update-video-thumbnail
Manually updates a video record in the database with a thumbnail URL.
Request Body:
{
"video_url": "gs://bucket-name/videos/video-id/video.mp4",
"thumbnail_url": "https://cdn.yiku.studio/thumbnails/video-id.jpg"
}Response (Success):
{
"success": true,
"message": "Video record updated with thumbnail URL",
"video_url": "gs://bucket-name/videos/video-id/video.mp4",
"thumbnail_url": "https://cdn.yiku.studio/thumbnails/video-id.jpg",
"updated_at": "2025-08-10T17:30:00.000Z"
}POST /cleanup-wrong-bucket
Cleans up files that were accidentally uploaded to the wrong bucket (undefined bucket).
Response:
{
"success": true,
"message": "Wrong bucket completely cleaned up",
"details": "Removed all files and structure from undefined bucket"
}POST /cleanup-wrong-structure
Cleans up incorrectly nested file structures in the R2 bucket.
Response:
{
"success": true,
"message": "Wrong file structure cleaned up",
"details": "Removed nested file structure from yiku-content bucket"
}GET /test-supabase
Tests the Supabase database connection and credentials.
Response:
{
"success": true,
"message": "Supabase connection successful",
"data": []
}GET /debug-env
Provides debugging information about environment variables, particularly Supabase configuration.
Response:
{
"success": true,
"message": "Environment variables debug info",
"data": {
"supabaseUrl": "https://your-project.supabase.co",
"supabaseKey": "eyJhbGciOiJIUzI1NiIs...",
"supabaseKeyLength": 123,
"nodeEnv": "production",
"allEnvKeys": ["NEXT_PUBLIC_SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY"]
}
}GET /metadata/:filename
Retrieves metadata for a specific file stored in R2 storage.
Parameters:
filename: The name of the file (e.g.,1754309685409.jpg)
Response:
{
"success": true,
"data": {
"Path": "thumbnails/1754309685409.jpg",
"Name": "1754309685409.jpg",
"Size": 13395,
"MimeType": "image/jpeg",
"ModTime": "2025-08-10T17:30:00.000Z"
}
}| Variable | Description | Default |
|---|---|---|
PORT |
Service port | 3000 |
NODE_ENV |
Environment mode | production |
MAX_DISK_USAGE |
Maximum disk usage percentage | 80 |
CLEANUP_INTERVAL |
Cleanup interval in milliseconds | 300000 (5 minutes) |
TEMP_DIR |
Temporary videos directory | ./temp/videos |
THUMBNAIL_DIR |
Temporary thumbnails directory | ./temp/thumbnails |
GOOGLE_APPLICATION_CREDENTIALS |
GCP service account key path | ./credentials/gcp-service-account.json |
GCP_PROJECT_ID |
Google Cloud project ID | Required |
R2_ACCOUNT_ID |
Cloudflare R2 account ID | Required |
R2_ACCESS_KEY_ID |
R2 access key ID | Required |
R2_SECRET_ACCESS_KEY |
R2 secret access key | Required |
R2_BUCKET_NAME |
R2 bucket name | yiku-content |
R2_PUBLIC_URL |
Public CDN URL | https://cdn.yiku.studio |
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL | Required |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key | Required |
All endpoints return appropriate HTTP status codes:
200: Success400: Bad Request (missing parameters)500: Internal Server Error
Error responses include:
success: falseerror: Error message- Additional context where applicable
The service automatically runs cleanup tasks every 5 minutes to remove temporary files older than 30 minutes.
yiku-thumbnail/
├── temp/
│ ├── videos/ # Temporary video files
│ └── thumbnails/ # Temporary thumbnail files
├── credentials/ # GCP service account key
├── server.js # Main application file
├── package.json # Dependencies
└── .env # Environment configuration
express: Web framework@supabase/supabase-js: Supabase clientfs-extra: Enhanced file system operationsnode-cron: Cron job schedulingdotenv: Environment variable loading
gsutil: Google Cloud Storage CLI toolffmpeg: Video processing toolrclone: R2 storage CLI toolgcloud: Google Cloud CLI tool
- The service automatically creates temporary directories on startup
- Thumbnails are generated at 400x600px with aspect ratio preservation
- All temporary files are automatically cleaned up after successful processing
- The service validates authentication before processing requests
- Database updates are optional and only occur when
video_urlis provided