Ir para a navegação

Guia de Segmentos

Visão Geral

Segmentos permitem sincronizar diferentes clipes de áudio para diferentes intervalos de tempo dentro de um único vídeo em uma chamada de API. Isso possibilita sincronização labial multi-falantes ao permitir que você atribua diferentes entradas de áudio para diferentes partes do seu vídeo. Usando segmentos, você pode:

  • Sincronizar labialmente diferentes clipes de áudio para diferentes partes do seu vídeo
  • Usar uma porção específica da entrada de áudio para sincronizar um segmento com precisão de tempo
  • Usar entradas de áudio e texto para fala para sincronizar múltiplos segmentos com diferentes tipos de entrada em uma única geração

Conceitos Básicos

Para usar o recurso de segmentos, você precisa fornecer um array de nível superior segments com cada item definindo um intervalo/segmento de tempo do vídeo, cada um com sua própria configuração de áudio.

Segmento

Cada item de segmento possui as seguintes propriedades:

startTime
doubleRequired

Tempo de início do segmento em segundos

endTime
doubleRequired

Tempo de término do segmento em segundos

audioInput
SegmentAudioInputRequired

Configuração de áudio com refId e recorte opcional

optionsOverride
SegmentOptionsOverride

Sobrescreve opções de geração para este segmento específico

audioInput

Cada segmento requer exatamente um audioInput. audioInput possui as seguintes propriedades:

refId
stringRequired

ID de referência da entrada de áudio/texto para fala a ser usada neste segmento

startTime
double

Tempo de início opcional (em segundos) para recortar o áudio referenciado. Quando especificado, endTime também deve ser fornecido

endTime
double

Tempo de término opcional (em segundos) para recortar o áudio referenciado. Quando especificado, startTime também deve ser fornecido

O audioInput especificado será usado para sincronizar labialmente o segmento de vídeo entre startTime e endTime.

optionsOverride

Cada segmento pode opcionalmente sobrescrever as opções de geração de nível superior. Isso permite aplicar configurações diferentes por segmento, incluindo direcionar diferentes falantes.

Para vídeos multi-falantes, use active_speaker_detection para direcionar uma pessoa diferente em cada segmento. Veja Seleção de Falante - API para detalhes completos sobre opções de seleção de falante.

sync_mode
SyncMode

Sobrescreve o modo de sincronização para este segmento

temperature
double

Sobrescreve a expressividade (0-1) para este segmento

occlusion_detection_enabled
boolean

Sobrescreve a detecção de oclusão para este segmento

active_speaker_detection
ActiveSpeaker

Sobrescreve a detecção de falante ativo para este segmento. Útil quando diferentes segmentos têm falantes diferentes. Aceita as mesmas opções que o active_speaker_detection de nível superior:

  • auto_detect: detecta e direciona automaticamente o falante ativo
  • v3: usa ASD v3
  • frame_number + coordinates: especifica manualmente o falante por quadro e ponto
  • bounding_boxes: fornece caixas delimitadoras por quadro se você tiver dados de detecção
  • bounding_boxes_url: aponta para um arquivo JSON externo contendo caixas delimitadoras (recomendado para vídeos longos para evitar cargas úteis grandes na requisição)

Como funciona o tempo e duração dos segmentos

Quando o áudio de um segmento e sua janela de vídeo (endTime − startTime) têm durações diferentes, o sync_mode decide como a discrepância é resolvida - e o modo escolhido altera a duração efetiva desse segmento na saída:

sync_modeáudio mais longo que a janelaáudio mais curto que a janela
bouncevídeo faz bounce (vai para frente e depois para trás) para cobrir o áudiojanela é cortada para o áudio
loopvídeo faz loop para cobrir o áudiojanela é cortada para o áudio
cut_offsaída é cortada para a faixa mais curta (a janela)janela é cortada para o áudio
silencetoca o áudio completo (vídeo é preenchido para cobri-lo)janela completa toca; áudio é preenchido com silêncio
remaptempo do vídeo é esticado para coincidir com o áudiojanela é cortada para o áudio

Em resumo, o comprimento efetivo de um segmento é cut_off → min(áudio, janela), silence → max(áudio, janela), e loop / bounce / remap → o comprimento do áudio.

As mesmas regras se aplicam a uma geração de segmento único (não-segments), onde a “janela” é o vídeo inteiro. Um áudio de 30s em um vídeo de 15s com sync_mode: cut_off produz uma saída de 15s (cortada para o vídeo); silence / loop / bounce / remap produzem uma saída de aproximadamente 30s.

A saída pode ser maior que o vídeo fonte

Cada segmento posiciona seu trecho de áudio em sua própria janela na linha do tempo, e cada janela se expande para acomodar seu áudio (conforme o sync_mode acima). Quando há lacunas entre segmentos, essas janelas expandidas deslocam o restante da linha do tempo - então a saída pode ser maior que o vídeo fonte. Por exemplo, dois segmentos [1s - 3s] e [5s - 8s] em um vídeo de 10s podem produzir uma saída de aproximadamente 16,8s: cada janela esticada para acomodar seu áudio completo. Isso é comportamento esperado, não um erro.

Para manter a saída com a mesma duração do vídeo fonte, recorte cada trecho de áudio para sua janela com audioInput.startTime/endTime, assim o trecho tem exatamente a duração da janela e a janela não se expande:

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

Aqui o trecho de áudio de 2 segundos preenche exatamente a janela de 2 segundos, então a linha do tempo - e a duração da saída - permanecem alinhadas com a fonte.

Exemplos de Uso da 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"),
),
],
)

Múltiplos Segmentos com Entrada de Áudio Única

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"
)

Múltiplos Segmentos com Entrada de Áudio Única

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"
)

Segmentos com Opções por Segmento

Use optionsOverride para aplicar configurações de geração diferentes para cada segmento.

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
)

Direcione Falantes Diferentes por Segmento

Use active_speaker_detection em optionsOverride para direcionar falantes diferentes em cada segmento. Isso é útil quando um vídeo tem várias pessoas e diferentes segmentos devem sincronizar labialmente com falantes diferentes.

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"
)

Veja Seleção de Falante - API para detalhes sobre as opções de active_speaker_detection.

Melhores Práticas

Planejando Seus Segmentos

  1. Mapeie sua linha do tempo: Identifique segmentos de vídeo e necessidades correspondentes de áudio
  2. Prepare os arquivos de áudio: Garanta qualidade de áudio e duração apropriada
  3. Teste os limites dos segmentos: Verifique transições suaves entre segmentos

Preparação do Áudio

  • Use qualidade de áudio consistente em todos os segmentos e no áudio do vídeo.
  • Para melhores resultados, assegure alinhamento de tempo adequado com os segmentos do vídeo. Se a duração do segmento e a duração do áudio correspondente não coincidirem, confie no sync_mode para determinar como lidar com a discrepância.

Solução de Problemas

Erros Comuns

Forneça um array segments de nível superior ao usar múltiplas entradas de áudio ou texto.

# ❌ 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"
)

Certifique-se de que todas as entradas de áudio tenham valores válidos para url ou assetId e que os valores refId referenciados existam em suas entradas de áudio ou texto.

# ❌ 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"
)

Este erro ocorre quando o audio_input de um segmento está sem um refId ou o refId está vazio. Cada segmento deve referenciar uma entrada válida de áudio ou texto através do seu 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"
)

Este erro ocorre quando um segmento referencia um refId que não existe em suas entradas de áudio ou texto. Certifique-se de que todos os valores refId referenciados correspondam exatamente aos definidos em suas entradas.

# ❌ 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"
)

O startTime de cada segmento deve ser menor ou igual ao seu endTime. Segmentos de duração zero (onde startTime é igual a endTime) são permitidos para casos de uso como pontos de recorte de duração zero.

# ❌ 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"}
}
]

Ao especificar limites de segmento usando quadros em vez de segundos, startFrame deve ser estritamente menor que endFrame. Diferente dos segmentos baseados em tempo que permitem tempos iguais de início e fim, segmentos baseados em quadros requerem pelo menos um quadro de diferença.

# ❌ 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"}
}
]

Ao recortar áudio dentro de um segmento, tanto startTime quanto endTime devem ser fornecidos, e startTime deve ser menor ou igual a 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
}
}
]

Certifique-se de ter pelo menos uma entrada de áudio ou texto com um refId válido ao usar segmentos.

# ❌ 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"
)

Recursos Relacionados