1 points par GN⁺ 1 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Le principal goulot d’étranglement d’une archive vidéo n’était pas le montage mais l’impossibilité de faire des recherches, et l’objectif était de transformer des clips non étiquetés en un index interrogeable en anglais
  • Avec une conception local-first, des fichiers sidecar .description.md sont créés à côté de chaque clip, en extrayant en un seul appel de vision la note, l’éclairage, le lieu, la transcription, les mots-clés et une description en prose
  • Le pipeline assemble ffprobe, exiftool, Nominatim, ffmpeg, WhisperX, insightface et un modèle de vision pour générer métadonnées, GPS, images, transcription et embeddings de visages
  • Un MacBook Pro 16 pouces 2021 M1 Max 64 Go faisait tourner Gemma 4 31B Q4 dans LM Studio, et le swap a culminé à 50,89 Go pendant le traitement de masse
  • Un schéma structuré et des contraintes enum ont réduit les hallucinations, et il a été possible d’imaginer une configuration où le gros de l’indexation est traité en local avec un 31B, puis où seuls les 10 à 20 % de clips difficiles sont réévalués par un modèle cloud

Point de départ du problème : la recherche avant le montage

  • Pendant près de six mois passés dans le Maasai Mara, des vidéos tournées avec un iPhone, un DJI Pocket, un drone, un Nikon Z8 et des Ray-Ban Meta se sont accumulées, mais la plupart sont restées sans jamais être rouvertes
  • Les réseaux sociaux de Mara Hilltop étaient à l’arrêt depuis trois mois, non pas par manque de contenu mais par manque de temps de montage
  • Avec Claude Code et Opus 4.5/4.6, le travail de développement permettait désormais de longues exécutions d’agents et du travail en parallèle, et avec le lancement du premier hébergement payant de KaribuKit, le temps disponible pour monter des vidéos a encore diminué
  • La première solution envisagée consistait en une stack SaaS à 140 $/mois combinant Eddie AI, Higgsfield MCP, Submagic et Buffer, mais elle ne correspondait pas au vrai goulot d’étranglement
  • La vidéo générative par IA ne correspondait pas à une vraie marque de voyage, et afficher par erreur des scènes générées par IA à des voyageurs qui s’attendent à voir le lieu réel pouvait nuire à la confiance
  • Un rythme de publication réaliste était plus proche de 2 à 3 publications par semaine que de 3 à 5, ce qui rendait le plan initial voué à l’échec dès la deuxième semaine
  • DaVinci Resolve Studio et les fonctions IntelliSearch, Smart Bins et Voice to Subtitle de Resolve 21 couvraient déjà environ 70 % de ce qu’Eddie apportait
  • La configuration restante consistait à laisser Claude Code piloter Resolve via le MCP open source de DaVinci Resolve, et à n’utiliser ElevenLabs pour la voix off que sur les clips informatifs, ce qui faisait tomber le coût à 22 $/mois

Le vrai goulot d’étranglement : il faut un index avant un éditeur IA

  • Les éditeurs vidéo IA du marché partent du principe que les vidéos sont déjà étiquetées, alors qu’en pratique l’archive réelle était dispersée sous des noms comme IMG_*.mov, DJI_*.mp4 ou Mara june 2024 backup final FINAL
  • Eddie permet la recherche dans les transcriptions, mais ne pouvait pas retrouver dans une archive non étiquetée une scène comme « des éléphants sur une colline à l’heure dorée »
  • Les noms de fichiers, le dossier parent, les coordonnées GPS et le texte transcrit ne suffisent pas à connaître le contenu visuel d’un plan comme « un plan large au lever du soleil avec une girafe dans le cadre »
  • Le véritable levier n’était pas au niveau de l’éditeur mais en amont : il fallait d’abord un index capable de rendre l’archive interrogeable en anglais

Conception d’un indexeur local-first

  • L’architecture générale ressemblait aux builds natifs IA que SimbaStack développe pour ses clients, mais ici les décisions ont été rapides parce que la même personne était à la fois cliente et ingénieure
  • Quatre contraintes

    • Il fallait être local-first
      • L’archive de Mara Hilltop était sur un SSD physique et les vidéos personnelles sur le portable, et envoyer des milliers de clips de plusieurs gigaoctets dans le cloud n’avait de sens ni en coût ni en confidentialité
    • Il fallait des fichiers sidecar plutôt qu’une base centrale
      • Chaque clip reçoit un .description.md à côté de lui, consultable en texte brut avec grep
      • Même si l’indexeur casse plus tard, les fichiers restent là, et ils se déplacent avec les données d’un disque à l’autre
    • Il fallait extraire en un seul appel de vision toutes les informations nécessaires
      • Comme le passage vision sur les images extraites coûte cher, le schéma a été conçu large dès le départ pour récupérer, dès le premier appel, y compris les informations utiles plus tard
      • Cela comprenait la note, la qualité technique, l’éclairage, le moment de la journée, la palette de couleurs, la qualité audio, le nombre de personnes, les mots-clés, les visages, le lieu, la transcription, une description en prose, etc.
    • Il fallait pouvoir choisir entre trois backends vision
      • La valeur par défaut était la CLI de l’abonnement Claude Max, sans coût marginal
      • Quand la vitesse était nécessaire, l’API Anthropic était utilisée
      • Pour le traitement en masse, un backend local pointant vers LM Studio était utilisé, et c’était ce backend local qui était central

Pipeline de traitement par clip

  • ffprobe lit les métadonnées
  • exiftool lit latitude, longitude et altitude GPS, avec le même fonctionnement sur les vidéos iPhone, DJI Pocket et drone
  • Un géocodage inverse est effectué avec Nominatim, gratuit, limité en débit et sans besoin de clé API
  • ffmpeg extrait 5 images en 1920 px à intervalles réguliers
  • WhisperX réalise la transcription avec alignement mot à mot et séparation des locuteurs via pyannote, avec prise en charge de 97 langues dont l’hindi, l’anglais et le swahili
  • insightface détecte les visages et stocke des embeddings ArcFace 512 dimensions dans une base SQLite centrale des visages pour permettre plus tard la recherche de personnes dans toute l’archive
  • Le modèle de vision lit les images, une partie de la transcription et le contexte du dossier, puis renvoie un frontmatter YAML et une description en prose
  • Le résultat final est enregistré dans un sidecar .description.md à côté du clip
  • Dans un clip réel de Mara Hilltop, IMG_1103.MOV, le nom du fichier ne donnait aucun contexte, mais le sidecar généré par Gemma comprenait l’installation d’une tente de safari, un panoramique de la caméra allant de l’intérieur vers la savane, le type de plan et des usages possibles comme des reels marketing ou du B-roll de vlog de voyage
  • Au niveau du dossier, en plus des sidecars à côté de chaque clip, des fichiers _INDEX.json et _INDEX.md étaient générés en tête pour permettre des grep rapides et l’envoi aux LLM
  • L’implémentation complète tient dans environ 1 400 lignes de Python sous forme de skill Claude Code, écrit en grande partie par Claude Code, le rôle humain ayant porté sur l’architecture, les prompts, la conception du schéma et le triage des bugs

Un modèle local 31B sur un vieux MacBook

  • Le MacBook Pro 16 pouces M1 Max 64 Go RAM acheté en 2021 n’avait pas été choisi pour les LLM, mais pour faire tourner en même temps des onglets Chrome, DaVinci Resolve, Slack, Discord et Drive
  • Cinq ans plus tard, ce même portable traite une année d’archive vidéo avec Gemma 4 31B Q4 dans LM Studio
  • Dans LM Studio, un modèle de 28,40 Go était chargé en mémoire et l’API REST tournait sur 127.0.0.1:1234
  • Pendant le traitement de masse, les 64 Go de RAM ne suffisaient plus, et l’utilisation du swap a culminé à 50,89 Go selon Activity Monitor
  • Ce n’était pas un état tenable pour une journée de travail ordinaire, mais cela restait acceptable pour pousser la machine pendant un week-end
  • Le portable chauffait, les ventilateurs soufflaient fort, mais il continuait à générer des sidecars pendant que d’autres tâches tournaient
  • Ce modèle de MacBook Pro M1 Max 16 pouces montrait qu’un matériel vieux de cinq ans pouvait encore exécuter un modèle à 31B paramètres à une vitesse exploitable, et si les LLM locaux deviennent plus efficaces, il pourrait probablement servir encore 3 à 5 ans

Quatre bugs et leçons retenues

  • Changement d’API de séparation des locuteurs dans WhisperX 3.8

    • Dans WhisperX 3.8, whisperx.DiarizationPipeline a été déplacé vers le sous-module whisperx.diarize
    • L’argument de constructeur use_auth_token a été renommé en token, en suivant pyannote 3.x
    • La solution a été l’introspection de signature
    • Le script essaie d’abord token=, puis bascule sur use_auth_token= si le constructeur renvoie un TypeError
    • Quand on appelle des bibliothèques IA qui évoluent vite, des appels de constructeur défensifs sont une assurance peu coûteuse
  • La CLI Claude renvoyait des erreurs de permission comme si c’étaient des succès

    • Lors du premier test du backend CLI, les 4 sidecars sont revenus avec exactement le même texte : « I need permission to read the image frames... »
    • Le code de sortie était 0 et la sortie n’était pas vide, donc la vérification de succès du script passait
    • En mode non interactif, sans --permission-mode bypassPermissions, la CLI Claude renvoie le texte de refus de permission dans le corps de réponse au lieu de répondre au prompt
    • La solution a consisté à ajouter ce flag et à traiter comme erreur toute réponse courte contenant « I need permission » au lieu de l’accepter comme description
    • Quand on manipule des outils IA dans des scripts, les flux d’autorisation non interactifs cachent des échecs silencieux
  • Gemma renvoyait people_count: "many"

    • Le prompt vision demandait « integer or the string "many" if >10 », donc Gemma suivait correctement l’instruction
    • Le bug n’était pas dans le modèle mais dans la conception du schéma
    • Après correction, il a été explicitement demandé d’estimer un entier de 0 à 99, et les anciennes réponses "many" ont été converties de force dans le parseur
    • Les champs de schéma ne doivent pas être des unions du type int ou chaîne spécifique : il faut fixer le type, toujours entier ou toujours chaîne, pour simplifier les consommateurs downstream
  • Des clips de moto tremblants ont été écartés à tort

    • Le prompt initial de culling était plus proche de critères de portfolio photo, et classait le fort flou de mouvement, la mise au point molle et les tremblements dans cull
    • Un clip de moto de nuit filmé à main levée pendant un voyage en Espagne s’est donc retrouvé destiné au rejet, alors que ce flou faisait justement partie de l’atmosphère du souvenir
    • Le critère de culling a été redéfini : non plus « prise de vue imparfaite », mais « ce n’est pas une vraie trace du moment »
    • Les clips à rejeter ont été resserrés à des cas comme bouchon d’objectif, vidéo dans la poche, clip test de 2 secondes ou exposition complètement brûlée
    • Une archive photo peut être cullée de manière agressive, tandis que des souvenirs vidéo doivent l’être avec plus de souplesse ; même avec le même schéma, il faut des modes bien distincts

Conclusions tirées des schémas structurés et d’un modèle local

  • Les contraintes par énumération réduisent les hallucinations

    • Gemma 4 E4B décrivait une photo d’espace de coworking prise de nuit comme « brightly lit, abundant natural light, floor-to-ceiling windows », alors qu’à l’extérieur des fenêtres il faisait complètement nuit
    • En donnant au 31B un schéma structuré et en lui faisant choisir parmi golden_hour | bright_daylight | overcast | dim_interior | nighttime | mixed | unclear, il revenait à nighttime, aussi bien avec thinking-off qu’avec thinking-on
    • Le modèle peut inventer de fausses descriptions dans un texte libre, mais avec un enum il ne peut pas inventer une nouvelle valeur, seulement se tromper dans son choix
    • Le schéma s’est avéré plus sûr que de simples instructions
  • Un 31B local et des prompts structurés réduisent l’écart avec le cloud

    • Gemma 4 31B Q4 en mode thinking-off, avec un schéma structuré, produisait sur beaucoup de clips de test des sorties difficiles à distinguer de celles de Sonnet 4.6
    • La prime des modèles cloud valait surtout sur les 10 à 20 % de clips difficiles
    • Pour un travail de masse consistant à indexer des milliers de clips pendant la nuit, une architecture à deux niveaux passait bien à l’échelle : exécution en local, puis réévaluation dans le cloud des seuls clips marqués review par le local
  • Les éditeurs vidéo IA se battent à une couche trop haute

    • La couche qui a de la valeur n’était pas l’éditeur, mais un index consultable
    • Si l’on peut interroger en langage naturel quelque chose comme « clips de Mara tournés à main levée en intérieur, à l’heure dorée, avec des personnes, de plus de 8 secondes », alors l’éditeur au-dessus devient simple
    • Le marché des éditeurs vidéo IA se dispute une couche de surface posée sur un index inexistant, en sautant la condition préalable qu’est justement cet index

Étapes suivantes et limites

  • La prochaine étape consiste à créer un éditeur avec Claude Code comme orchestrateur, DaVinci Resolve MCP pour faire les coupes, et des voix off ElevenLabs sur les clips informatifs
  • Le voice cloning a des limites claires
    • Il n’est utilisé que pour du contenu utilitaire : indications, descriptions de chambres, versions multilingues, informations factuelles qu’on pourrait dire soi-même
    • Il n’est pas utilisé pour les avis ni pour les messages du fondateur
    • En 2026, les obligations de divulgation seront une réalité, et la confiance dans une marque d’hospitalité se perd facilement
  • Une fois l’index disponible, il devient inutile de scruber manuellement 47 Go de vidéos DJI Pocket pour trouver un plan large au lever du soleil
  • Aujourd’hui, sur un portable vieux de cinq ans, une année de vidéos de Mara Hilltop est devenue interrogeable en anglais, au prix d’un week-end et de 50 Go de swap
  • Les autres années encore stockées sur d’anciens SSD sont les prochaines à traiter
  • Les réseaux sociaux de Mara Hilltop ne sont pas encore relancés
    • L’indexeur ne résout que le problème de trouver les bons clips
    • L’autre moitié est l’éditeur qui les transforme en reels finalisés ; si cela fonctionne, un billet de suivi sera écrit, sinon il expliquera pourquoi cela a échoué
  • Il est possible que la bonne réponse soit d’embaucher quelqu’un
    • Trouver un monteur avec une sensibilité chaleureuse et attentive adaptée à Mara Hilltop peut être plus difficile qu’écrire un autre skill
    • L’objectif n’est pas de produire des reels façon MTV coupés de manière excessive
  • Le code est open source sur github.com/Simbastack-hq/framedex, et les PR comme les issues sont bienvenues

1 commentaires

 
GN⁺ 1 시간 전
Commentaires Hacker News
  • On dirait que Claude a choisi le mauvais URL à partager en écrivant l’article. Sauf si le dossier personnel est exposé vers l’extérieur, ~/.claude/skills/video-index/ n’est pas accessible, donc je me demande si tu pourrais partager le fichier Skill

    • C’est un peu la version moderne de la situation classique où un ami qui vient juste de commencer à programmer dit : « J’ai créé mon appli web, tu veux voir ? La voici : http://localhost:8080 »
    • Oups, c’était ma faute. Je suis en train de corriger ça, et je peux aussi partager le fichier Skill. Donne-moi 5 minutes
  • Mise à jour : j’ai créé ce dépôt à la hâte - https://github.com/Simbastack-hq/framedex
    La licence est MIT, et je n’ai pas encore pu le généraliser puis le tester correctement. Je vais bientôt tout reprendre sérieusement et ajouter d’autres mises à jour
    Les deux gros points de la TODO sont : 1) accélérer le montage vidéo dans DaVinci Resolve en exploitant cet index et l’aide de Claude, 2) pour l’instant je n’ai traité que la vidéo, mais je veux aussi l’étendre pour comprendre les milliers d’images fixes présentes sur l’appareil photo

  • Je ne comprends pas très bien pourquoi il faut autant de swap. Vu la bande passante mémoire nécessaire, ça risque d’user le SSD assez vite
    Le modèle quantifié en 4 bits de Gemma 4 31B devrait faire autour de 19 GiB, pas 28,4 GiB [1]. Je n’injecte pas souvent des images, donc je ne sais pas combien de mémoire supplémentaire il faut pour les mettre dans le contexte, mais ça ne devrait probablement pas dépasser 10 GiB
    En regardant le moniteur d’activité, on voit aussi plusieurs applis Electron ouvertes en plus de Handy et de la machine virtuelle pour Claude Code, qui semblent avoir chargé le modèle, donc la vraie cause vient sans doute plutôt de là. Une fois que le portable se met à gratter le disque à fond, ce genre d’applis se figera de toute façon, donc elles ne serviront plus à grand-chose
    [1] https://huggingface.co/mlx-community/gemma-4-31b-it-4bit

    • Oui. Je faisais aussi autre chose sur le portable quand j’ai pris la capture, donc j’aurais pu faire du ménage
      Cela dit, même si ça ramait un peu, j’ai trouvé impressionnant de pouvoir continuer à faire autre chose, même avec beaucoup d’onglets ouverts dans le navigateur Brave
  • Je me demande si tu savais que ça existe déjà, que c’est plutôt bien, et que ça n’avale pas 50 Go de swap
    https://github.com/iliashad/edit-mind

  • Très cool. J’aimerais avoir assez de RAM pour faire tourner des modèles en local. J’ai construit quelque chose de très similaire ces dernières semaines, mais moi je l’ai fait comme une appli Electron locale avec Whisper et ffmpeg, en ajoutant de la recherche sémantique et des embeddings pour discuter avec les vidéos
    L’analyse visuelle, le tagging et le chat vidéo communiquent avec Claude. Je me demande si ce projet envoie une seule image. Moi, avec un algorithme de détection de scènes personnalisé, je repère plusieurs images différentes par vidéo et je les envoie à Claude en une seule requête avec les sous-titres. C’est clairement la partie la plus coûteuse. Avec Sonnet 4.6 pour l’analyse et Haiku pour le tagging, ça revient à environ 1 dollar pour une heure de vidéo, et j’imagine que ce serait lent en local

    • Ce n’est pas une seule image, mais 5 frames par clip envoyées en une seule requête avec un extrait des sous-titres. Donc pour la partie consistant à mettre plusieurs frames et des sous-titres d’un coup, c’est la même approche
      En revanche, la façon de choisir les frames est le point faible. La détection de scènes aiderait clairement, et c’est la priorité n°1 de la feuille de route. Je serais curieux que tu partages comment tu choisis les frames dans la détection de scènes
      Je n’ai pas ajouté de recherche vectorielle, et j’ai préféré garder quelque chose de simple avec des fichiers Markdown génériques plus portables. Même si on déplace le SSD, la connaissance se déplace avec les fichiers ; il n’y a pas d’index à synchroniser, et le texte brut a l’avantage de survivre plus longtemps que l’outil. Cela dit, l’autre direction que tu évoques mérite aussi d’être explorée
    • Si tu veux réduire les coûts, tu peux essayer les modèles d’OpenRouter. Gemma 4 31B coûte 0,12 $ par million de tokens en entrée et 0,37 $ par million de tokens en sortie, alors que Haiku coûte 1 $ par million de tokens en entrée et 5 $ par million de tokens en sortie
      Il y a aussi d’autres options correctes. Gemini 3.1 Flash Lite est très bien pour ce genre de travail. En revanche, pas Gemini 3.5 Flash. Son tarif n’est pas intéressant
      https://openrouter.ai/google/gemma-4-31b-it
  • J’ai deux questions

    1. Je me demande ce qu’est l’index de recherche
    2. Dans l’exemple de description.md, il y a des éléments comme faces -> cluster_id. Je me demande si ça vient de l’index des visages de DaVinci Resolve. Dans une collection photo, les infos comme visages+noms et lieux sont vraiment importantes, mais les LLM généralistes gèrent mal ce genre de choses
      1. Ce ne sont que de simples fichiers sidecar .description.md en texte brut, placés à côté des vidéos pour chaque clip
        Plus tard, quand je brainstorme avec Claude en lui disant par exemple « je veux faire une vidéo sur les suites haut de gamme du lodge », il peut interroger ces fichiers et comprendre quelles vidéos seraient utiles
        Il y a aussi, à la racine du dossier, un fichier qui rassemble les descriptions textuelles pour faciliter la recherche. J’ai mis une image d’exemple sur le blog - https://blog.simbastack.com/_media/gvcycx2n.png
      2. Ça ne vient pas de DaVinci Resolve. Framedex est un pipeline autonome et Resolve n’intervient pas
        Les visages viennent d’insightface. Ils sont détectés avec RetinaFace du pack open source buffalo_l, exécuté en local sur CPU. Les visages sont détectés et encodés à partir de frames échantillonnées de chaque clip, puis une ligne est écrite dans ~/.framedex/faces.db
        Honnêtement, sur cette partie, je sais que ça s’accumule dans une base locale, mais je n’ai pas encore vraiment vérifié à quel point ça fonctionne bien. Je vais bientôt m’y pencher sérieusement
        Plus largement, c’est pour cela que framedex évite délibérément de confier au LLM le traitement des visages ou des lieux. Les visages sont gérés avec des embeddings insightface / ArcFace, ce qui permet une comparaison déterministe entre clips. Le modèle visuel ne fournit qu’un nombre approximatif de personnes et n’essaie pas d’identifier qui c’est
        Les lieux sont gérés via les GPS EXIF avec exiftool et le géocodage inverse de Nominatim/OpenStreetMap. Ce n’est pas une supposition, mais une métadonnée solide
        Le LLM ne fait que ce qu’il sait bien faire : description de scène, ambiance, type de plan, mots-clés, notes pour archiver/réviser/jeter, ce genre de choses. La dernière partie sur la notation peut se discuter
  • J’ai essayé de faire quelque chose de similaire sur un ThinkPad de 2015 avec Gemma. Heureusement, j’ai pu upgrader la mémoire, sinon ça aurait été assez pénible
    Je ne vais pas mentir : en faisant tourner llama.cpp, le ventilateur était à fond. Mais ça a fonctionné, et le travail a été fait

    • L’expression « le ventilateur tourne à fond » me laisse toujours perplexe. Si on veut finir les calculs le plus vite possible, est-ce qu’il ne faut pas forcément produire plus de chaleur puis l’évacuer ?
      J’ai l’impression que c’est parfois utilisé comme métaphore pour dire « ça utilise 100 % des ressources », et c’est probablement le sens ici, mais dans d’autres contextes, c’est clairement exprimé comme une vraie plainte
  • Je ne pense pas que la majorité des hôtes Airbnb seraient d’accord avec l’idée que « la vidéo générée par IA n’a pas sa place pour une vraie marque de voyage »
    Quant à « la crucifixion sur TripAdvisor », je ne comprends vraiment pas comment des hôtes Airbnb qui publient de faux hébergements arrivent encore à survivre

    • Honnêtement, je me pose beaucoup de questions là-dessus moi aussi. Je gère un safari lodge, mais je n’ai pas envie d’aller vers de la vidéo IA bas de gamme
      En même temps, faire de vraies vidéos prend du temps et ralentit tout le processus
  • Je pense que les applications IA B2C sont structurellement limitées parce qu’il est difficile d’y construire un contexte personnalisé
    Si un modèle local compétent pouvait faire à grande échelle, depuis zéro, la collecte de contexte, la recherche, le tagging, etc., ce serait une vraie percée

    • J’ai créé une appli IA B2C entièrement locale qui renomme les fichiers en fonction du contexte, et elle est gratuite
      Tu lui donnes plusieurs captures d’écran et elle essaie de leur attribuer intelligemment un nom en fonction de leur contenu. Pareil pour la vidéo, les PDF, etc.
      Mais comme tu le dis, Apple risque simplement d’intégrer ça comme fonctionnalité, donc je n’ai même pas essayé de la vendre
      https://finalfinalreallyfinaluntitleddocumentv3.com/
    • Entièrement d’accord. Ici, Claude et moi avons fait ensemble ce travail de recherche et d’essais-erreurs en brainstormant
      Mais à mon avis, ce n’est qu’une question de temps avant que les agents deviennent assez intelligents pour que même des amis non techniques puissent simplement dire « organise les vidéos de ce dossier pour que je puisse les comprendre » et obtenir exactement ça
    • Je me demande vraiment si la solution est forcément le modèle local. Des API de modèles sans état n’apportent-elles pas le même avantage ? Je comprends que le local puisse être « moins cher » selon l’usage, mais cela fait longtemps que nous louons du stockage et des ressources de calcul dans le cloud en payant une prime