Générateur de Shaders
Envoi uniquement : crée un job de génération backend, retourne un jobId. Utilisez l'outil track_progress pour le cycle de vie du job après la soumission.
Utilisez toujours generate.ts pour les nouveaux shaders. L'écriture manuelle est réservée à la modification du code d'une ressource existante — jamais comme solution de secours lorsque la génération échoue.
Règle du catalogue — essayez d'abord les ressources existantes avant de générer
Avant de générer un shader, appelez browse_library sauf si l'utilisateur nomme un identifiant de ressource exact déjà visible dans read_project.
browse_library est la source de vérité pour les effets intégrés, les transitions intégrées et les ressources d'effet/transition du projet. Les ressources intégrées ont des identifiants globaux stables, pas des ressources DB par projet, donc elles peuvent ne pas apparaître dans les listes de ressources read_project.
Appliquez les entrées du catalogue avec edit_item, n'appelez pas submit_shader.
Exemples de bonnes recherches dans le catalogue :
browse_library(query: "zoom")
browse_library(category: "transitions", query: "dissolve")
browse_library(category: "audio-fx")
Générez uniquement lorsqu'aucune entrée du catalogue ne correspond suffisamment à l'intention de l'utilisateur.
builtin:zoom est lié uniquement à la piste — NE PAS utiliser lié à l'élément
Le mode d'effet par défaut est "item-bound" (attacher à un seul élément via targetItemId). builtin:zoom NE s'affiche PAS en mode lié à l'élément — le moteur de rendu lit les données de zoom exclusivement à partir des éléments d'effet liés à la piste. Un zoom lié à un élément s'insère dans la DB en silence mais n'affiche rien dans l'aperçu.
Utilisez mode: "track-bound" avec trackId + trackBoundFrom + trackBoundDurationInFrames. Ces trois champs sont obligatoires.
# Zoom sur l'intégralité du clip vidéo
edit_item(json: '{"adds":[{"type":"effect","assetId":"builtin:zoom","mode":"track-bound","trackId":"<clip-trackId>","trackBoundFrom":<clip-fromFrame>,"trackBoundDurationInFrames":<clip-durationInFrames>,"propertyOverrides":{"magnification":1.5,"shape":"hold"}}]')
# Zoom sur une sous-plage du clip (ex. images 90–150 seulement, un zoom punch sur un temps fort)
edit_item(json: '{"adds":[{"type":"effect","assetId":"builtin:zoom","mode":"track-bound","trackId":"<trackId>","trackBoundFrom":90,"trackBoundDurationInFrames":60,"propertyOverrides":{"magnification":2,"shape":"punch"}}]')
Obtenez trackId / fromFrame / durationInFrames de read_project (chaque élément vidéo/image liste son trackId et sa plage d'images temporelle).
| Clé | Type | Plage / valeurs | Défaut | Notes |
|---|---|---|---|---|
magnification | number | 1–4 | 1.5 | Facteur de zoom ; 1 = pas de zoom, 2 = zoom 2× |
focalPointX | number | 0–1 | 0.5 | Point focal horizontal (0 = gauche, 1 = droite) |
focalPointY | number | 0–1 | 0.5 | Point focal vertical (0 = haut, 1 = bas) |
shape | select | punch / hold / slow-push / instant | hold | Courbe d'animation |
focalMode | select | auto / manual | auto | auto choisit le sujet ; manual utilise focalPoint |
easeInFrames | number | 0–60 | 8 | Images pour l'accélération en entrée |
easeOutFrames | number | 0–60 | 8 | Images pour la décélération en sortie |
Omettez entièrement propertyOverrides pour un zoom par défaut. Envoyez uniquement les clés que vous souhaitez modifier — sémantique de correctif.
Lié à la piste vs lié à l'élément — la règle générale
Les éléments d'effet dans le schéma ont deux modes :
item-bound(défaut) :targetItemIdseulement. L'effet couvre toute la lecture de l'élément cible. Fonctionne pour les effets de shader, les LUT, les étalonnages, les flous.track-bound:trackId+trackBoundFrom+trackBoundDurationInFrames. L'effet couvre une plage temporelle sur une piste, indépendamment de tout élément. Requis pourbuiltin:zoom; également valable pour tout effet de shader lorsque vous souhaitez qu'il couvre une plage temporelle spécifique (par exemple, un changement de couleur de type transition à la frontière de deux clips).
Par défaut, utilisez lié à l'élément pour les effets de shader. Utilisez lié à la piste lorsque (a) la ressource l'exige (zoom), ou (b) l'effet doit couvrir une plage temporelle qui ne correspond pas à un seul élément.
Propriétés des LUT intégrées
edit_item(json: '{"adds":[{"type":"effect","targetItemId":"<clip-id>","assetId":"builtin:slog3-s709","propertyOverrides":{"intensity":1}}]')
| Clé | Type | Plage | Défaut | Notes |
|---|---|---|---|---|
intensity | number | 0–1 | 1 | Force de la LUT ; 1 = appliquée pleinement |
Pour changer : supprimez l'effet et ajoutez-le à nouveau avec un assetId différent. Pour supprimer : supprimez l'élément d'effet.
Ceci est distinct des ressources LUT .cube téléchargées par l'utilisateur (voir "Appliquer une ressource LUT existante" ci-dessous) — celles-ci utilisent un chemin de code différent avec assetId:"lut".
Garde de statut bêta
La génération de nouveaux shaders est en phase bêta. Avant de générer, avertissez l'utilisateur et attendez une confirmation explicite.
Utilisez la langue de l'utilisateur. Chinois : "新的特效/转场生成目前还是 beta 阶段,可能会有不稳定的问题。如果你坚持要做,我可以帮你实现。" Ignorez si l'utilisateur a déjà accusé réception dans la même requête.
Cibles prises en charge
Les effets et transitions s'appliquent aux éléments video, image, et gif.
Routage par type
Avant de générer quoi que ce soit, vérifiez d'abord deux chemins sans génération :
- Entrée du catalogue — utilisez
browse_librarypour les effets/transitions intégrés et du projet. - Ressource LUT
.cubetéléchargée par l'utilisateur qui existe déjà dans la bibliothèque du projet — chemin de code séparé, voir "Appliquer une ressource LUT existante" ci-dessous. La ressource apparaît dansread_projectavectype: lut.
| L'utilisateur souhaite | --type |
|---|---|
| Apparence vidéo (couleur, flou, lueur, grain, distorsion) | effect |
| Étalonnage / look (bleu-orange, cinématographique, vintage, style LUT) | effect |
| Contrôle de visibilité (masque, révélé, fondu, découpe de forme, dégradé) | effect |
| Mélange entre clips (crossfade, dissolve, slide, cube 3D / retournement de page) | transition |
"Style LUT" dans le tableau signifie générer un nouvel étalonnage de couleur GLSL qui ressemble à une LUT — uniquement lorsque l'utilisateur veut quelque chose de nouveau. S'il veut appliquer un fichier .cube déjà dans la bibliothèque, ne générez pas ; liez plutôt la ressource existante.
Il n'y a pas de générateur séparé de LUT ou de masque pour le chemin de génération — ce sont tous des effect.
Appliquer une ressource LUT existante
Les fichiers .cube téléchargés par l'utilisateur deviennent des ressources lut. En appliquer un à un clip n'est pas une génération — c'est un seul appel edit_item qui attache un élément d'effet dont assetId est la chaîne littérale "lut" et dont propertyOverrides.lut lie l'identifiant réel de la ressource LUT. (Contrat hérité ; l'API LUT unifiée lie directement l'identifiant de la ressource d'effet LUT — voir la description de edit_item.)
edit_item(json: '{"adds":[{"type":"effect","targetItemId":"<clip-id>","assetId":"lut","propertyOverrides":{"intensity":1,"lut":{"assetId":"<lut-asset-id>","assetType":"lut","type":"asset"}}}]}')
Points clés :
assetIdest la chaîne littérale"lut", pas l'identifiant de la ressource LUT. L'identifiant réel de la ressource LUT va danspropertyOverrides.lut.assetId.intensityest de 0 à 1 ; défaut 1 (pleine force).targetItemTypepar défaut àvideo; prend également en chargeimage,gif.- Pour changer une LUT sur un effet existant : mettez à jour
propertyOverrides.lut.assetIdavec le nouvel identifiant de ressource LUT. - Pour supprimer : supprimez l'élément d'effet.
N'appelez pas generate.ts pour ce chemin. Ne passez pas d'identifiant réel de ressource LUT comme assetId — l'éditeur vérifie assetId === "lut" pour acheminer vers le moteur de rendu LUT ; passer un UUID n'affiche rien en silence.
Utilisation
Avant d'appeler submit_shader, reformulez l'intention de l'utilisateur en une phrase concrète, puis procédez immédiatement. Après le retour de track_progress, indiquez ce qui a été produit en une ligne — ne demandez PAS "要保留还是重新生成".
submit_shader({
type: "effect",
prompt: "Aberration chromatique avec séparation RVB",
name: "Aberration Chromatique",
});
submit_shader({
type: "transition",
prompt: "Fondu enchaîné doux avec bord adouci",
name: "Fondu Enchaîné",
});
submit_shader({
type: "effect",
prompt: "Étalonnage cinématographique bleu-orange",
});
submit_shader({
type: "effect",
prompt: "Version plus forte",
referenceAssetIds: ["effet_asset_id"],
});
Stratégie
- Soumettez, puis arrêtez. Dites à l'utilisateur que le job a été créé.
- Utilisez l'outil
track_progresspour le statut/attente après la soumission. - La génération produit toujours une ressource de bibliothèque — ne refusez jamais parce que la timeline n'est pas prête.
- L'application est séparée et facultative. Appliquez uniquement lorsque l'utilisateur le demande explicitement ("加到视频", "apply", "用到第一段"). En cas d'ambiguïté, par défaut, limitez-vous à la bibliothèque.
Modification des propriétés existantes
Chaque fois que vous êtes sur le point de modifier asset.properties d'un shader, item.propertyOverrides d'un effet/transition appliqué, ou de promouvoir une valeur de shader codée en dur, lisez d'abord references/property-changes.md.
Cela rappelle que les properties d'un shader sont un tableau, mais que les types de propriétés autorisés pour les shaders sont uniquement number, boolean, color, select, et vec2. Les propriétés Motion Graphic sont également des tableaux, mais utilisent un ensemble de types différents.
Paramètres
| Param | Description | Défaut |
|---|---|---|
type | "effect" ou "transition" (obligatoire) | — |
prompt | Description du shader (obligatoire) | — |
name | Nom de la ressource affiché dans la bibliothèque | — |
referenceAssetIds | Identifiants de ressources. Identifiant d'image → le modèle la REGARDE pour l'inspiration visuelle. Identifiant d'effet/transition → réutilise son code comme ancrage de style (≤1 par soumission, le type doit correspondre à type). | — |
Sortie
Retourne { success, job: { jobId, status }, manage: { status, wait, watch } }.
Application à la timeline
Uniquement lorsque l'utilisateur le demande explicitement. Appelez d'abord read_project pour un état frais de la timeline.
Effet
edit_item(json: '{"adds":[{"type":"effect","targetItemId":"<id>","assetId":"<id>","enabled":true,"propertyOverrides":{}}]}')
Transition
Nécessite deux points de terminaison adjacents sur la même piste. edit_item valide la faisabilité de la jonction en direct et refuse les durées qui nécessiteraient des images figées ou un chevauchement de transitions voisines. Si l'ajout échoue, réessayez avec la durationInFrames suggérée, rognez les clips pour exposer les poignées, supprimez/raccourcissez les transitions voisines, ou conservez une coupe franche.
edit_item(json: '{"adds":[{"type":"transition","assetId":"<id>","outgoingItemId":"<id1>","incomingItemId":"<id2>","durationInFrames":30}]}')
Validation et vérification
Validation backend
Lors de la génération via generate.ts, le backend gère la validation automatiquement (transpile, sécurité AST, structure de classe, nouvelle tentative en cas d'échec).
Vérification manuelle du code
N'écrivez JAMAIS de code de shader à partir de zéro. Utilisez toujours generate.ts pour les nouveaux shaders. Cette section est UNIQUEMENT pour modifier le code de shader existant qui a déjà été généré.
Lorsque vous écrivez du code de shader manuellement, lisez d'abord ${CLAUDE_SKILL_DIR}/references/design-principles.md. Si la modification touche aux propriétés modifiables, lisez également ${CLAUDE_SKILL_DIR}/references/property-changes.md.
Flux de travail typique :
read_projectavec leassetIddu shader etcode: true— lisez le code source actuel.- Modifiez la source dans votre propre contexte.
edit_assetavecaction=update, le mêmeassetId, et le code de remplacement complet en ligne dansjson.code. La validation s'exécute automatiquement lors de la mise à jour — si le code est invalide, la mise à jour est rejetée avec les détails de l'erreur.