Avatar
← Back to Portfolio

Anime Directory

YouTube-style video platform on GCP: users upload via signed URLs, Pub/Sub triggers a Cloud Run FFmpeg service (360p transcode + thumbnails), metadata in Firestore, videos served with short-lived signed URLs through a Next.js web client.

TypeScriptNext.jsReactNode.jsExpressDockerFFmpegFirebase AuthCloud Functions (HTTPS Callable)Cloud RunCloud StorageFirestorePub/Sub
Visit Live Site →

The Problem

I wanted a “YouTube-style” experience for anime clips where users can upload large videos and immediately get an optimized playback experience. The challenge: moving big files reliably from the browser, processing them at scale (transcoding + thumbnails), keeping costs low, and preventing duplicate work when background jobs retry. All of this had to be secure (no public write keys) and snappy in the UI.

The Solution

I built a fully serverless pipeline on Google Cloud. The web app (Next.js) authenticates with Firebase and requests a short-lived V4 signed URL to upload directly to a “raw” Cloud Storage bucket—bypassing my servers. A bucket notification triggers Pub/Sub, which pushes to a Cloud Run service. That service uses FFmpeg to transcode to 360p and extract a thumbnail, uploads results to a “processed” bucket, and writes a video document in Firestore. The UI lists processed videos and streams via a short-lived signed URL, so files stay private.

Architecture & Technical Details

System Architecture

Flow: Next.js (Firebase Auth) → callable function returns signed upload URL → client PUTs to Raw Bucket → GCS notifies Pub/Sub → Pub/Sub push → Cloud Run (FFmpeg) → Processed Bucket + thumbnail → Firestore videos document → Next.js lists & streams via signed read URL.

  • Idempotency guard in Cloud Run avoids duplicate work.
  • Filename validation + least-privilege service accounts for safety.
  • -movflags +faststart for quicker playback start.
  • Optional public thumbnails; processed videos stay private.

Anime Directory Architecture

Ingest → Raw Bucket → Pub/Sub → Cloud Run (FFmpeg) → Processed Bucket + Firestore → Next.js

Key Features

  • Direct-to-GCS uploads via short-lived V4 signed URLs.
  • Background transcoding (FFmpeg) to 360p.
  • Automatic thumbnail extraction and upload.
  • Firestore video documents with status: processing/processed/ failed.
  • Secure playback via short-lived signed read URLs.
  • Next.js grid home, watch page, and “Suggested videos”.
  • Serverless, pay-for-what-you-use infrastructure.

Challenges & Key Learnings

Technical Challenges

  • Handling Pub/Sub redelivery without double-processing.
  • Next.js image optimization with private thumbnails (workarounds & config).
  • Signed URL content-type matching and filename sanitizing.
  • Cloud Run cold starts and resource tuning for FFmpeg.
  • Artifact Registry + Docker workflow across regions.

What I Learned

  • Designing idempotent, retry-safe serverless pipelines with Pub/Sub.
  • FFmpeg presets and flags that improve startup latency.
  • Secure file handling with GCS signed URLs (read/write) and IAM.
  • Next.js caching behavior (ISR) for dynamic yet cacheable pages.
  • Practical production wiring on GCP (Cloud Run, AR, Firestore).