Passer à la navigation

Guide des segments

Vue d ensemble

Les segments vous permettent de synchroniser différents clips audio avec différentes plages temporelles d’une même vidéo en un seul appel API. Cela permet le lip sync multi-locuteurs en assignant différentes entrées audio à différentes parties de votre vidéo. Avec les segments, vous pouvez :

  • Appliquer du lip sync à différents clips audio sur différentes parties de votre vidéo
  • Utiliser une portion précise d’une entrée audio pour synchroniser un segment avec un timing exact
  • Utiliser à la fois des entrées audio et synthèse vocale pour synchroniser plusieurs segments avec différents types d’entrées dans une seule génération

Concepts de base

Pour utiliser la fonctionnalité de segments, fournissez un tableau segments au niveau racine. Chaque élément définit une plage temporelle ou un segment vidéo, avec sa propre configuration audio.

Segment

Chaque segment accepte les propriétés suivantes :

startTime
doubleRequired

Heure de début du segment, en secondes

endTime
doubleRequired

Heure de fin du segment, en secondes

audioInput
SegmentAudioInputRequired

Configuration audio avec refId et recadrage facultatif

optionsOverride
SegmentOptionsOverride

Remplacer les options de génération pour ce segment précis

audioInput

Chaque segment nécessite exactement un audioInput. audioInput accepte les propriétés suivantes :

refId
stringRequired

ID de référence de l entrée audio ou synthèse vocale à utiliser pour ce segment

startTime
double

Heure de début facultative (en secondes) pour recadrer l’audio référencé. Si elle est spécifiée, endTime doit aussi être fourni

endTime
double

Heure de fin facultative (en secondes) pour recadrer l’audio référencé. Si elle est spécifiée, startTime doit aussi être fourni

L audioInput spécifié sera utilisé pour appliquer le lip sync au segment vidéo entre startTime et endTime.

optionsOverride

Chaque segment peut facultativement remplacer les options de génération définies au niveau racine. Cela vous permet d appliquer des paramètres différents par segment, y compris cibler différents locuteurs.

Pour les vidéos multi-locuteurs, utilisez active_speaker_detection pour cibler une personne différente dans chaque segment. Consultez sélection du locuteur - API pour tous les détails sur les options de sélection du locuteur.

sync_mode
SyncMode

Remplacer le mode Sync pour ce segment

temperature
double

Remplacer l expressivité (0-1) pour ce segment

occlusion_detection_enabled
boolean

Remplacer la détection d’occlusion pour ce segment

active_speaker_detection
ActiveSpeaker

Remplacer l’active speaker detection pour ce segment. Utile lorsque différents segments ont différents locuteurs. Accepte les mêmes options que active_speaker_detection au niveau racine :

  • auto_detect : détecter et cibler automatiquement le locuteur actif
  • v3 : utiliser ASD v3
  • frame_number + coordinates : spécifier manuellement le locuteur par frame et par point
  • bounding_boxes : fournir des bounding boxes par frame si vous avez des données de détection
  • bounding_boxes_url : pointer vers un fichier JSON externe contenant les bounding boxes (recommandé pour les longues vidéos afin d éviter de gros payloads de requête)

Fonctionnement du timing et de la durée des segments

Lorsque l’audio d’un segment et sa fenêtre vidéo (endTime - startTime) ont des durées différentes, sync_mode décide comment résoudre l écart. Le mode choisi modifie la durée effective de ce segment dans la sortie :

sync_modeaudio plus long que la fenêtreaudio plus court que la fenêtre
bouncela vidéo rebondit (avant puis arrière) pour couvrir l’audiofenêtre raccourcie à la durée de l’audio
loopla vidéo boucle pour couvrir l’audiofenêtre raccourcie à la durée de l’audio
cut_offsortie coupée à la piste la plus courte (la fenêtre)fenêtre raccourcie à la durée de l’audio
silencelit tout l’audio (vidéo prolongée pour le couvrir)toute la fenêtre est lue ; l’audio est complété par du silence
remapla vidéo est étirée temporellement pour correspondre à l’audiofenêtre raccourcie à la durée de l’audio

En bref, la durée effective d’un segment est cut_off -> min(audio, fenêtre), silence -> max(audio, fenêtre), et loop / bounce / remap -> la durée de l’audio.

Les mêmes règles s’appliquent à une génération à segment unique (sans segments), où la “fenêtre” correspond à toute la vidéo. Un audio de 30 s sur une vidéo de 15 s avec sync_mode: cut_off produit une sortie de 15 s (coupée à la vidéo) ; silence / loop / bounce / remap produisent une sortie d’environ 30 s.

La sortie peut être plus longue que votre vidéo source

Chaque segment place sa prise audio dans sa propre fenêtre sur la timeline, et chaque fenêtre s’étend pour correspondre à son audio (selon le sync_mode ci-dessus). Lorsqu il y a des espaces entre les segments, ces fenêtres étendues décalent le reste de la timeline, donc la sortie peut être plus longue que la vidéo source. Par exemple, deux segments [1s-3s] et [5s-8s] sur une vidéo de 10 s peuvent produire une sortie d’environ 16,8 s : chaque fenêtre est étirée pour contenir toute sa prise audio. C est le comportement attendu, pas un bug.

Pour conserver une sortie de la même longueur que la vidéo source, recadrez chaque prise audio à sa fenêtre avec audioInput.startTime/endTime, afin que la prise ait exactement la même durée que la fenêtre et que celle-ci ne s’étende pas :

{
"startTime": 1,
"endTime": 3,
"audioInput": { "refId": "audio_1", "startTime": 0, "endTime": 2 }
}

Ici, la tranche audio de 2 secondes remplit exactement la fenêtre de 2 secondes. La timeline, et donc la durée de sortie, reste alignée avec la source.

Exemples d utilisation de l’API

from sync import Sync
from sync.common import Audio, Video
sync = Sync()
response = sync.generations.create(
input=[
Video(url="https://assets.sync.so/docs/example-video.mp4"),
Audio(url="https://assets.sync.so/docs/example-audio.wav", ref_id="audio_1"),
],
model="lipsync-2",
segments=[
GenerationSegment(
start_time=2,
end_time=5,
audio_input=SegmentAudioInput(ref_id="audio_1"),
),
],
)

Plusieurs segments avec une seule entrée audio

from sync import Sync
from sync.common import Audio, Video, TTS
sync = Sync()
response = sync.generations.create(
input=[
Video(url="https://assets.sync.so/docs/example-video.mp4"),
Audio(url="https://assets.sync.so/docs/example-audio.wav", ref_id="audio_1")
],
segments=[
{
"startTime": 2,
"endTime": 5,
"audioInput": {"refId": "audio_1", "startTime": 2, "endTime": 5}
},
{
"startTime": 6,
"endTime": 8,
"audioInput": {"refId": "audio_1", "startTime": 6, "endTime": 8}
}
],
model="lipsync-2"
)

Plusieurs segments avec une seule entrée audio

from sync import Sync
from sync.common import Audio, Video, TTS
sync = Sync()
response = sync.generations.create(
input=[
Video(url="https://assets.sync.so/docs/example-video.mp4"),
Audio(url="https://assets.sync.so/docs/example-audio.wav", ref_id="audio_1"),
Audio(url="https://assets.sync.so/docs/example-audio.wav", ref_id="audio_2")
],
segments=[
{
"startTime": 2,
"endTime": 5,
"audioInput": {"refId": "audio_1", "startTime": 2, "endTime": 5}
},
{
"startTime": 6,
"endTime": 8,
"audioInput": {"refId": "audio_2", "startTime": 6, "endTime": 8}
}
],
model="lipsync-2"
)

Segments avec options par segment

Utilisez optionsOverride pour appliquer des paramètres de génération différents à chaque segment.

from sync import Sync
from sync.common import Audio, Video
sync = Sync()
response = sync.generations.create(
input=[
Video(url="https://assets.sync.so/docs/example-video.mp4"),
Audio(url="https://assets.sync.so/docs/audio1.wav", ref_id="audio_1"),
Audio(url="https://assets.sync.so/docs/audio2.wav", ref_id="audio_2")
],
segments=[
{
"startTime": 0,
"endTime": 5,
"audioInput": {"refId": "audio_1"},
"optionsOverride": {
"sync_mode": "loop",
"temperature": 0.3
}
},
{
"startTime": 5,
"endTime": 10,
"audioInput": {"refId": "audio_2"},
"optionsOverride": {
"sync_mode": "cut_off",
"temperature": 0.7
}
}
],
model="lipsync-2",
options={"sync_mode": "bounce"} # Default for segments without override
)

Cibler différents locuteurs par segment

Utilisez active_speaker_detection dans optionsOverride pour cibler différents locuteurs dans chaque segment. C est utile lorsqu’une vidéo contient plusieurs personnes et que différents segments doivent appliquer le lip sync à différents locuteurs.

from sync import Sync
from sync.common import Audio, Video
sync = Sync()
response = sync.generations.create(
input=[
Video(url="https://assets.sync.so/docs/two-speakers.mp4"),
Audio(url="https://assets.sync.so/docs/speaker-a.wav", ref_id="audio_a"),
Audio(url="https://assets.sync.so/docs/speaker-b.wav", ref_id="audio_b")
],
segments=[
{
"startTime": 0,
"endTime": 5,
"audioInput": {"refId": "audio_a"},
"optionsOverride": {
"active_speaker_detection": {
"frame_number": 0,
"coordinates": [200, 300] # Point on speaker A's face
}
}
},
{
"startTime": 5,
"endTime": 10,
"audioInput": {"refId": "audio_b"},
"optionsOverride": {
"active_speaker_detection": {
"frame_number": 150,
"coordinates": [600, 300] # Point on speaker B's face
}
}
}
],
model="lipsync-2"
)

Consultez sélection du locuteur - API pour plus de détails sur les options active_speaker_detection.

Bonnes pratiques

Planifier vos segments

  1. Cartographiez votre timeline : identifiez les segments vidéo et les besoins audio correspondants
  2. Préparez les fichiers audio : assurez une bonne qualité audio et une durée adaptée
  3. Testez les limites des segments : vérifiez que les transitions entre segments sont fluides

Préparation audio

  • Utilisez une qualité audio cohérente sur tous les segments et l’audio de la vidéo.
  • Pour de meilleurs résultats, assurez un alignement temporel correct avec les segments vidéo. Si la durée du segment et la durée audio correspondante ne correspondent pas, utilisez sync_mode pour déterminer comment gérer l écart.

Dépannage

Erreurs courantes

Fournissez un tableau segments au niveau racine lorsque vous utilisez plusieurs entrées audio ou texte.

# ❌ This will fail
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio1.wav"), # Multiple audio without segments
Audio(url="audio2.wav")
],
model="lipsync-2"
)
# ✅ This will work
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio1.wav", ref_id="a1"),
Audio(url="audio2.wav", ref_id="a2")
],
segments=[
{"start_time": 0, "end_time": 10, "audio_input": {"refId": "a1"}},
{"start_time": 10, "end_time": 20, "audio_input": {"refId": "a2"}}
],
model="lipsync-2"
)

Assurez-vous que toutes les entrées audio ont des valeurs url ou assetId valides, et que les valeurs refId référencées existent dans vos entrées audio ou texte.

# ❌ Missing refId reference
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1")
],
segments=[
{"start_time": 0, "end_time": 10, "audio_input": {"refId": "missing"}} # Wrong refId
],
model="lipsync-2"
)
# ✅ Correct refId reference
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1")
],
segments=[
{"start_time": 0, "end_time": 10, "audio_input": {"refId": "audio1"}} # Correct refId
],
model="lipsync-2"
)

Cette erreur se produit lorsque audio_input d’un segment n’a pas de refId ou que le refId est vide. Chaque segment doit référencer une entrée audio ou texte valide via son refId.

# ❌ Missing refId in segment
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1")
],
segments=[
{
"start_time": 0,
"end_time": 10,
"audio_input": {} # Missing refId
}
],
model="lipsync-2"
)
# ✅ Include refId in segment
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1")
],
segments=[
{
"start_time": 0,
"end_time": 10,
"audio_input": {"refId": "audio1"} # Valid refId
}
],
model="lipsync-2"
)

Cette erreur se produit lorsqu’un segment référence un refId qui n existe pas dans vos entrées audio ou texte. Assurez-vous que toutes les valeurs refId référencées correspondent exactement à celles définies dans vos entrées.

# ❌ Segment references unknown refId
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1") # refId is "audio1"
],
segments=[
{
"start_time": 0,
"end_time": 10,
"audio_input": {"refId": "nonexistent"} # References unknown refId
}
],
model="lipsync-2"
)
# ✅ Segment references existing refId
response = sync.generations.create(
input=[
Video(url="video.mp4"),
Audio(url="audio.wav", ref_id="audio1") # refId is "audio1"
],
segments=[
{
"start_time": 0,
"end_time": 10,
"audio_input": {"refId": "audio1"} # References existing refId
}
],
model="lipsync-2"
)

Le startTime de chaque segment doit être inférieur ou égal à son endTime. Les segments de durée nulle (où startTime est égal à endTime) sont autorisés pour des cas comme des points de recadrage de durée nulle.

# ❌ Invalid: startTime greater than endTime
segments=[
{
"startTime": 10,
"endTime": 5, # endTime must be >= startTime
"audioInput": {"refId": "audio1"}
}
]
# ✅ Valid: startTime less than endTime
segments=[
{
"startTime": 0,
"endTime": 10,
"audioInput": {"refId": "audio1"}
}
]
# ✅ Valid: startTime equals endTime (zero-length segment)
segments=[
{
"startTime": 5,
"endTime": 5,
"audioInput": {"refId": "audio1"}
}
]

Lorsque vous spécifiez les limites d’un segment avec des frames au lieu de secondes, startFrame doit être strictement inférieur à endFrame. Contrairement aux segments temporels qui autorisent des heures de début et de fin identiques, les segments basés sur des frames nécessitent au moins une frame de différence.

# ❌ Invalid: startFrame greater than or equal to endFrame
segments=[
{
"startFrame": 100,
"endFrame": 0, # endFrame must be > startFrame
"audioInput": {"refId": "audio1"}
}
]
# ❌ Invalid: startFrame equals endFrame (not allowed for frames)
segments=[
{
"startFrame": 50,
"endFrame": 50, # endFrame must be > startFrame
"audioInput": {"refId": "audio1"}
}
]
# ✅ Valid: startFrame less than endFrame
segments=[
{
"startFrame": 0,
"endFrame": 100,
"audioInput": {"refId": "audio1"}
}
]

Lorsque vous recadrez l’audio dans un segment, startTime et endTime doivent tous les deux être fournis, et startTime doit être inférieur ou égal à endTime.

# ❌ Incomplete crop range
segments=[
{
"startTime": 0,
"endTime": 10,
"audioInput": {
"refId": "audio1",
"startTime": 5 # Missing endTime
}
}
]
# ❌ Invalid: startTime greater than endTime
segments=[
{
"startTime": 0,
"endTime": 10,
"audioInput": {
"refId": "audio1",
"startTime": 15,
"endTime": 5 # endTime must be >= startTime
}
}
]
# ✅ Valid: complete crop range with startTime <= endTime
segments=[
{
"startTime": 0,
"endTime": 10,
"audioInput": {
"refId": "audio1",
"startTime": 5,
"endTime": 15
}
}
]
# ✅ Valid: zero-duration crop point (startTime equals endTime)
segments=[
{
"startTime": 0,
"endTime": 10,
"audioInput": {
"refId": "audio1",
"startTime": 5,
"endTime": 5
}
}
]

Assurez-vous d avoir au moins une entrée audio ou texte avec un refId valide lorsque vous utilisez des segments.

# ❌ This will fail - no audio or text inputs
response = sync.generations.create(
input=[
Video(url="https://example.com/video.mp4")
],
segments=[
{"start_time": 0, "end_time": 10, "audio_input": {"refId": "missing"}}
],
model="lipsync-2"
)
# ✅ This will work - includes text input
response = sync.generations.create(
input=[
Video(url="https://example.com/video.mp4"),
TTS(
provider={
"name": "elevenlabs",
"voiceId": "EXAVITQu4vr4xnSDxMaL",
"script": "Hello world"
},
ref_id="text1"
)
],
segments=[
{"start_time": 0, "end_time": 10, "audio_input": {"refId": "text1"}}
],
model="lipsync-2"
)

Ressources connexes