feat: YouTube music download system with admin dashboard

Sidecar architecture: edge functions (auth + DB) → youtube-worker container
(youtubei.js for playlist metadata, yt-dlp for audio downloads).

- Edge functions: youtube-playlist, youtube-process, youtube-status (CRUD)
- youtube-worker sidecar: Node.js + yt-dlp, downloads M4A to Supabase Storage
- Admin music page: import playlists, process queue, inline genre editing
- 12 music genres with per-track assignment and import-time defaults
- DB migrations: download_jobs, download_items tables with genre column
- Deploy script and CI workflow for edge functions + sidecar
This commit is contained in:
Millian Lamiaux
2026-03-26 10:47:05 +01:00
parent 8926de58e5
commit 3d8d9efd70
21 changed files with 2426 additions and 0 deletions

View File

@@ -34,6 +34,28 @@ export type Json =
| { [key: string]: Json | undefined }
| Json[]
export const MUSIC_GENRES = [
'edm', 'hip-hop', 'pop', 'rock', 'latin', 'house',
'drum-and-bass', 'dubstep', 'r-and-b', 'country', 'metal', 'ambient',
] as const
export type MusicGenre = typeof MUSIC_GENRES[number]
export const GENRE_LABELS: Record<MusicGenre, string> = {
'edm': 'EDM',
'hip-hop': 'Hip Hop',
'pop': 'Pop',
'rock': 'Rock',
'latin': 'Latin',
'house': 'House',
'drum-and-bass': 'Drum & Bass',
'dubstep': 'Dubstep',
'r-and-b': 'R&B',
'country': 'Country',
'metal': 'Metal',
'ambient': 'Ambient',
}
export interface Database {
public: {
Tables: {
@@ -137,6 +159,47 @@ export interface Database {
last_login: string | null
}
}
download_jobs: {
Row: {
id: string
playlist_url: string
playlist_title: string | null
status: 'pending' | 'processing' | 'completed' | 'failed'
total_items: number
completed_items: number
failed_items: number
created_by: string
created_at: string
updated_at: string
}
Insert: {
id?: string
playlist_url: string
playlist_title?: string | null
status?: 'pending' | 'processing' | 'completed' | 'failed'
total_items?: number
completed_items?: number
failed_items?: number
created_by: string
}
Update: Partial<Omit<Database['public']['Tables']['download_jobs']['Insert'], 'id'>>
}
download_items: {
Row: {
id: string
job_id: string
video_id: string
title: string | null
duration_seconds: number | null
thumbnail_url: string | null
status: 'pending' | 'downloading' | 'completed' | 'failed'
storage_path: string | null
public_url: string | null
error_message: string | null
genre: MusicGenre | null
created_at: string
}
}
}
}
}