No description
Find a file
2026-08-06 15:27:02 +00:00
client Add encoder detection, settings tabs, home refresh & landscape jubeat layout 2026-08-03 02:11:33 +02:00
data Big update. flemme d'ecrire 2026-08-02 23:26:51 +02:00
server Add encoder detection, settings tabs, home refresh & landscape jubeat layout 2026-08-03 02:11:33 +02:00
tools Big update. flemme d'ecrire 2026-08-02 23:26:51 +02:00
.dockerignore docker: ajouter Dockerfile multi-stage + docker-compose + entrypoint (ffmpeg, fonts CJK, seed data) 2026-08-06 15:04:58 +00:00
.env.example Big update. flemme d'ecrire 2026-08-02 23:26:51 +02:00
.gitignore Big update. flemme d'ecrire 2026-08-02 23:26:51 +02:00
docker-compose.yml docker: ajouter Dockerfile multi-stage + docker-compose + entrypoint (ffmpeg, fonts CJK, seed data) 2026-08-06 15:04:58 +00:00
docker-entrypoint.sh docker: ajouter Dockerfile multi-stage + docker-compose + entrypoint (ffmpeg, fonts CJK, seed data) 2026-08-06 15:04:58 +00:00
Dockerfile docker: aligner le chemin des settings (symlink server/data -> data) — settingsStore lit server/data/settings.json 2026-08-06 15:27:02 +00:00
package-lock.json Add encoder detection, settings tabs, home refresh & landscape jubeat layout 2026-08-03 02:11:33 +02:00
package.json Big update. flemme d'ecrire 2026-08-02 23:26:51 +02:00
README.md docker: ajouter Dockerfile multi-stage + docker-compose + entrypoint (ffmpeg, fonts CJK, seed data) 2026-08-06 15:04:58 +00:00

VerseLink

Outil web local pour découper / composer des vidéos Chunithm depuis un album Immich, avec prévisualisation temps réel, marqueurs de scores Kamaitachi, rotation et rendu FFmpeg vertical 9:16.

Stack

  • Backend : Node.js + Express (workspaces npm)
  • Frontend : React + Vite + react-router-dom
  • Sources : Immich (album vidéos), Kamaitachi (scores, API V3)
  • Rendu : FFmpeg (h264_nvenc) + sharp (génération overlay score / rank)
  • Données : Fichiers JSON locaux (data/) + catalogue songs Chunithm (data/gameSongData/chunithm.json)

Structure du projet

VerseLink/
├── client/              # Frontend React (Vite)
│   ├── src/
│   │   ├── api.js             # Client API
│   │   ├── App.jsx            # Route config
│   │   ├── pages/
│   │   │   ├── VideosPage.jsx       # Liste des vidéos de l'album
│   │   │   ├── EditorPage.jsx       # Éditeur vidéo
│   │   │   └── ExportsPage.jsx      # File d'export
│   │   └── components/
│   │       ├── VideoEditor.jsx      # Éditeur principal (trim, métadonnées, export)
│   │       ├── VideoList.jsx        # Grille des vidéos
│   │       ├── MusicSelectionModal.jsx  # Sélecteur de musique Chunithm
│   │       ├── Timeline.jsx         # Timeline avec marqueurs de scores
│   │       ├── LiveExportPreview.jsx    # Prévisualisation temps réel du rendu 9:16
│   │       ├── Menu.jsx             # Navigation latérale + statut file
│   │       └── ExportQueue.jsx      # Mini file d'attente (compact)
│   └── vite.config.js       # Proxy /api → backend
├── server/              # Backend Express
│   └── src/
│       ├── config.js           # Configuration .env
│       ├── index.js            # Server entry point
│       ├── routes/
│       │   ├── album.js        # GET /api/album, GET /api/config
│       │   ├── assets.js       # GET /api/assets/:id, PUT state, vidéo/thumbnail proxy, kamai-suggestions
│       │   ├── render.js       # POST /api/render, /api/render/preview-frame, /api/render/queue/…
│       │   ├── localdata.js    # GET /api/local-data
│       │   └── data.js         # GET /api/data (songs), GET /api/covers
│       └── services/
│           ├── immich.js       # Client API Immich
│           ├── kamaitachi.js   # Client API Kamaitachi V3
│           ├── ffmpeg.js       # Rendu FFmpeg (filter complex, overlay, téléchargement)
│           ├── renderQueue.js  # File d'attente persistante (queue.json)
│           ├── timings.js      # Fenêtre d'enregistrement + parsing timestamps
│           └── store.js        # Store JSON local (timings.json)
├── tools/               # Génération d'assets Chunithm
│   ├── generateRank.cjs        # Génération badges rank (S, S+, SS, …)
│   ├── generateScore.cjs       # Génération chiffres score arc-en-ciel
│   ├── templates/              # Template spritesheet CHUNITHM
│   └── output/                 # Images rank pré-générées
├── data/
│   ├── gameSongData/chunithm.json  # Catalogue songs Chunithm (feat. sheets, difficultés, jackets)
│   ├── covers/                     # Jackets mis en cache
│   └── mask/                       # Masques PNG pour overlay
└── .env.example         # Template de configuration

Setup

cp .env.example .env
# Édite .env avec tes infos Immich / Kamaitachi
npm install
npm run dev

Docker 🐳

Le projet peut tourner en conteneur (serveur + client buildé + ffmpeg inclus).

# Lancer avec Docker Compose
cp .env.example .env        # optionnel : les réglages passent surtout par les Settings de l'app
sudo docker compose up --build -d
  • UI + API : http://localhost:3847
  • Les données sont persistées dans le volume verselink-data (catalogue, masques, exports, settings)
  • Le codec par défaut est h264_nvenc (GPU NVIDIA). Sans GPU, passe en libx264 (logiciel) dans les Settings de l'app.

Détails de l'image :

Élément Détail
Build Multi-stage : client React buildé (Vite) puis runtime Node 24
ffmpeg Inclus dans l'image + police CJK (wqy-zenhei) pour les overlays
Données seed Catalogue songs + masques copiés automatiquement au premier démarrage si le volume est vide
Port 3847
Entrypoint Initialise les dossiers runtime (output, raw, cache, covers)

Workspaces npm

Le projet utilise npm workspaces. Les scripts principaux :

Commande Description
npm run dev Lance server + client en parallèle
npm run dev:server Server seulement (avec --watch)
npm run dev:client Client Vite seulement
npm run build Build client (production)
npm run start Lance server seul (production, sert le client build)

Permissions Immich (API key)

  • album.read
  • asset.read
  • asset.view
  • asset.download

Configuration (.env)

PORT=3847                 # Port API (défaut)
HOST=0.0.0.0              # Bind host

# --- Immich ---
IMMICH_URL=https://immich.example.com
IMMICH_API_KEY=ta_cle_api
IMMICH_ALBUM_ID=id_album_immich
IMMICH_ALBUM_NAME=ChuniRaw   # Nom d'affichage (optionnel)

# --- Kamaitachi (optionnel) ---
KAMAITACHI_URL=https://kamai.tachi.ac
KAMAITACHI_API_KEY=ta_cle_kamai
KAMAITACHI_USER=ton_pseudo
KAMAITACHI_GAME=chunithm      # V3: chunithm (pas chunithm/Single)
KAMAITACHI_PLAYTYPE=          # Laisser vide pour Single (mono-playtype)

# --- Dossiers locaux ---
WORK_DIR=./data
OUTPUT_DIR=./data/output

# --- Police pour FFmpeg (optionnel) ---
FFMPEG_FONT_PATH=             # Chemin vers .ttf/.ttc
                               # Défauts : DejaVuSans-Bold.ttf, wqy-zenhei.ttc (CJK)

# --- Jackets Chunithm (optionnel) ---
CHUNI_SONG_COVER_URL=         # URL base pour les covers (ex: https://assets.example.com/covers/)

Fonctionnalités détaillées

1. Album Immich

  • Liste toutes les vidéos d'un album Immich
  • Grille avec vignettes, durée, statut téléchargement
  • Badges fenêtre d'enregistrement et suggestions Kamaitachi
  • Rafraîchissement manuel

2. Fenêtre d'enregistrement

VerseLink déduit automatiquement la fenêtre temporelle de chaque vidéo :

  • Début : extrait du nom de fichier VID_YYYYMMDD_HHMMSS (heure locale téléphone)
  • Fin : métadonnée Immich localDateTime (mêmes chiffres locaux)
  • Fuseau horaire : configurable (défaut Europe/Paris)

Les scores Kamaitachi dont timeAchieved tombe dans cette fenêtre sont associés à la vidéo.

3. Intégration Kamaitachi (API V3)

Deux niveaux de matching :

  1. /scores/recent → les 100 derniers scores. Si la vidéo est récente, match direct.
  2. /sessions/recent + session details → si la vidéo est plus vieille que les 100 scores, recherche dans les sessions.

Les suggestions s'affichent dans l'éditeur sous forme de chips cliquables : appliquer une suggestion remplit automatiquement titre, artiste, difficulté, score, grade et positionne les marqueurs de coupe.

4. Éditeur vidéo

  • Lecteur vidéo avec timeline et marqueurs
  • Découpe : réglage début/fin (curseurs + champs numériques)
  • Rotation : 90° / 180° / 270°
  • Sélecteur de musique : modal avec recherche par titre, artiste, version, difficulté. Utilise le catalogue data/gameSongData/chunithm.json (feat. covers, sheets, internal levels).
  • Métadonnées : titre, artiste, difficulté, score, grade, internal level
  • Prévisualisation temps réel : rendu FFmpeg 9:16 du frame courant avec tous les overlays (jacket, score, rank, textes)

5. Rendu FFmpeg

Le rendu vertical produit une vidéo 1080×1920 avec :

  • Fond flou (video + jacket en arrière-plan)
  • Vidéo source redimensionnée centrée (1200px de large)
  • Jacket : recadrée avec masques (PNG alpha), bordure arrondie
  • Score : chiffres arc-en-ciel Chunithm (via generateScore.cjs)
  • Rank : badge rank Chunithm (S, S+, SS, … via generateRank.cjs)
  • Texte : titre, artiste, difficulté (avec couleur par difficulté) via drawtext
  • Cache des images (score, jacket) pour éviter les régénérations

Codec vidéo : h264_nvenc (NVENC), audio : aac.

6. File d'attente d'export

  • Ajout à la file avec toutes les métadonnées
  • File persistante (data/queue.json) : les jobs sont re-chargés au redémarrage
  • Statuts : queued → running (download → encoding) → done / error
  • Progression : téléchargement (vitesse, ETA, taille) + encodage (pourcentage)
  • Téléchargement du fichier final depuis l'interface
  • Rafraîchissement automatique toutes les 3 secondes

7. Outils de génération

  • tools/generateRank.cjs : génère les badges rank Chunithm (S, S+, SS, SS+, SSS, SSS+) à partir d'une spritesheet template
  • tools/generateScore.cjs : génère les chiffres score arc-en-ciel (dernière ligne du template Chunithm) pour n'importe quel nombre
  • Utilisés automatiquement par le serveur lors du rendu

8. Overlays manuels / fallback

Si pas de Kamaitachi configuré ou pas de match :

  • Saisie manuelle des scores dans le GUI
  • Sauvegarde dans data/timings.json
  • Optionnel : segments JSON dans la description Immich : [{"start":12.5,"end":98.3,"label":"Song"}]
  • Parsing de patterns start-end dans la description

API Routes

Méthode Route Description
GET /api/config Configuration exposée au client
GET /api/album Liste des vidéos de l'album
GET /api/assets/:id Détail d'un asset vidéo
PUT /api/assets/:id/state Sauvegarde état éditeur (scores, cut, rotation, notes)
GET /api/assets/:id/thumbnail Proxy vignette Immich
GET /api/assets/:id/video Proxy vidéo Immich (range support)
GET /api/assets/:id/download Téléchargement local vidéo
GET /api/assets/:id/kamai-suggestions Suggestions scores Kamaitachi
GET /api/render/preview-frame Frame PNG 9:16 (GET, avec params query)
POST /api/render/preview-frame Frame PNG 9:16 (POST, avec body)
POST /api/render/render Rendu vidéo complet
POST /api/render/queue/add Ajout à la file d'attente
GET /api/render/queue/status Statut de la file d'attente
GET /api/render/download/:name Téléchargement fichier rendu
GET /api/local-data Données locales (data.json racine)
GET /api/data Catalogue songs (data.json)
GET /api/covers Liste covers locales
GET /api/health Healthcheck

Kamaitachi — configuration

Les variables d'environnement dans .env :

KAMAITACHI_URL=https://kamai.tachi.ac
KAMAITACHI_API_KEY=ta_cle
KAMAITACHI_USER=ton_pseudo
KAMAITACHI_GAME=chunithm
KAMAITACHI_PLAYTYPE=

Obtenir la clé API Kamaitachi

  1. Connecte-toi sur kamai.tachi.ac
  2. Va dans Integrations / Developer → crée un API Client
  3. Utilise le Client File Flow : https://kamai.tachi.ac/client-file-flow/TON_CLIENT_ID
  4. Kamaitachi te fournit la clé
  5. Mets ton pseudo exact (sensible à la casse) dans KAMAITACHI_USER

API V3 : le game path est /chunithm (plus /chunithm/Single). Les jeux multi-playtype deviennent /iidx-sp, etc.

Data

data/gameSongData/chunithm.json

Catalogue des chansons Chunithm utilisé pour le sélecteur de musique. Structure :

  • Songs avec title, artist, category, version, imageName (jacket)
  • Sheets par difficulté (basic → ultima) avec level, internalLevel, note counts

Fichiers locaux (WORK_DIR)

Fichier / Dossier Rôle
data/timings.json Store des états éditeur (scores, cuts, rotation)
data/queue.json File d'attente persistante
data/raw/ Vidéos téléchargées depuis Immich
data/output/ Vidéos rendues
data/cache/ Images mises en cache (scores, placeholders)
data/covers/ Jackets téléchargés
data/mask/ Masques PNG pour overlay jacket/box

FFmpeg

Requis avec support h264_nvenc pour l'encodage GPU. L'overlay utilise drawtext avec police wqy-zenhei pour le support CJK.

Sur Arch / CachyOS : pacman -S ffmpeg wqy-zenhei

Roadmap

  • Liste des vidéos de l'album Immich
  • Lecteur + timeline avec marqueurs scores
  • Cut début/fin manuel
  • Rotation 90°/180°/270°
  • Sauvegarde locale des timings
  • Rendu vertical FFmpeg (overlay jacket, score, rank, textes)
  • File d'attente persistante
  • Prévisualisation temps réel du rendu
  • Intégration Kamaitachi (matching scores → vidéos)
  • Catalogue songs Chunithm + sélecteur musique
  • Génération assets rank/score (CHUNITHM style)
  • Preview layout avec masques customisables
  • Push YouTube / Shorts / TikTok / Insta
  • Accès distant (Tailscale / Cloudflare Tunnel)