API de codec de vídeo preferido pelo editor
Um guia prático para definir preferências de codec por emissora, entender como essas preferências interagem com a negociação e confirmar qual codec está realmente sendo usado durante uma sessão ao vivo.
Este tópico inclui as seguintes seções:
- Pré-requisitos
- Visão geral
- Escolhendo um modo
- Sequências recomendadas de codecs para cenários comuns
- Como funciona a negociação de codecs
- Definição de preferências por plataforma
- Verificando o codec em uso
- Melhores práticas
Pré-requisitos
Antes de usar a API do Codec de Vídeo Preferencial por meio do SDK, é necessário habilitá-la nas configurações do seu projeto:
- Acesse o Account da Video API e selecione seu projeto.
- Nas configurações do projeto, selecione o codec de vídeo preferencial no nível do projeto.
- Aplique as configurações necessárias para habilitar as preferências de codec no nível do SDK.
Observação: Sua seleção afeta apenas o projeto selecionado. Saiba mais sobre os codecs compatíveis na Codecs de vídeo guia.
Visão geral
A Video API de codec de vídeo preferencial do editor permite que cada editor declare sua própria prioridade de codec, independentemente do codec preferencial definido no nível do projeto, configurado no Account da Video API. Você pode fornecer uma lista ordenada explícita de codecs ou delegar a decisão ao SDK em modo automático.
Importante: Esta API define um preferência, e não uma restrição. Outros codecs ainda podem ser negociados caso os preferidos não estejam disponíveis. A preferência influencia a ordem em que os codecs aparecem na oferta do SDP, conferindo-lhes maior prioridade durante a negociação.
Utilize esta API quando a configuração no nível do projeto não for específica o suficiente para suas necessidades. Alguns cenários comuns incluem:
-
Sessões com dispositivos mistos. Diferentes emissores na mesma sessão se beneficiam de codecs diferentes. Com as preferências por emissor, cada dispositivo pode definir a ordem dos codecs que melhor lhe convém.
-
Editoras especializadas em determinados temas. Um desenvolvedor de aplicativos de compartilhamento de tela pode se beneficiar do VP9, enquanto um desenvolvedor de aplicativos de câmera na mesma sessão prefere o VP8 por oferecer maior compatibilidade.
-
Deixar que o SDK decida. Se você não quiser definir uma lista de forma estática, o modo automático delega a escolha ao SDK.
Se todos os reprodutores do seu aplicativo devem usar o mesmo codec e a configuração no nível do projeto já reflete essa escolha, você não precisa desta API.
O VP8 é um codec de implementação obrigatória, compatível com todos os terminais. Como todos os codecs compatíveis são automaticamente adicionados como opções alternativas, o VP8 está sempre disponível como última opção alternativa, mesmo que você não o inclua explicitamente na sua lista.
Para obter informações básicas sobre os próprios codecs VP8, H.264 e VP9, tabelas de cobertura de codecs e a configuração de codec preferencial no nível do projeto, consulte o Codecs de vídeo guia.
Escolhendo um modo
Automático
Passe a corda 'automatic' (Web, React Native) ou chamar o método de fábrica correspondente nos SDKs nativos. O SDK avalia o ambiente local e determina uma ordem de prioridade adequada para os codecs.
Use o modo automático quando:
- Você quer que o SDK se adapte a diferentes navegadores e dispositivos sem precisar manter sua própria lógica específica para cada dispositivo.
- Você prefere uma abordagem compatível com versões futuras. O modo automático incorporará heurísticas de seleção mais sofisticadas em futuras versões do SDK; assim, as applications que o adotarem hoje se beneficiarão dessas melhorias sem precisar alterar o código.
Observação: As heurísticas utilizadas pelo modo automático evoluirão com o tempo. As versões iniciais aplicam uma estratégia de seleção básica. Versões futuras do SDK poderão levar em consideração sinais adicionais, como recursos de hardware, condições de rede e topologia da sessão. Considere o modo automático como o padrão recomendado, a menos que você tenha um motivo específico para definir uma lista de forma estática.
Manual
Forneça uma matriz ordenada de codecs. O primeiro elemento tem a prioridade mais alta:
['vp9', 'vp8'] prefer VP9, fall back to VP8, then remaining codecs
['h264'] prefer H.264; remaining codecs (VP8, VP9) are appended automatically as fallbacks
['vp8', 'h264', 'vp9'] explicit full ordering: VP8 first, then H.264, then VP9
Use o modo manual quando souber exatamente qual é a melhor ordem de codecs para um determinado editor ou dispositivo. Essa configuração substitui o codec preferencial definido no nível do projeto no painel de controle.
Observação: Os codecs especificados definem a ordem de prioridade, mas todos os demais codecs compatíveis são sempre acrescentados como opções alternativas. Por exemplo, ao definir ['vp9'] isso significa que o VP9 é o formato preferencial, mas o VP8 e o H.264 continuam disponíveis para negociação caso o VP9 não esteja disponível.
Padrão
Se você não definir preferredVideoCodecs De qualquer forma, o editor utiliza o codec preferencial no nível do projeto, configurado no painel de controle. Esse é o mesmo comportamento que ocorria antes da existência dessa API.
Comparação
| Modo | Quando usar | Preparado para o futuro? |
|---|---|---|
| Automático | Você quer que o SDK escolha a melhor ordem | Sim, benefícios decorrentes das atualizações do SDK |
| Lista de manuais | Você sabe a ordem exata dos codecs dessa editora | Não, você é quem cuida da lista |
| Padrão | A configuração no nível do projeto é suficiente | N/A, utiliza a configuração do projeto |
Sequências recomendadas de codecs para cenários comuns
Ao usar o modo manual, a ordem dos codecs que você define depende do tipo de sessão, do público e do caso de uso. A tabela abaixo lista cenários comuns com uma sugestão de preferredVideoCodecs valor e o raciocínio por trás dele.
| Cenário | Ordem sugerida | Por que |
|---|---|---|
| Sessão de grande porte / webinar (encaminhado) | ['vp9', 'vp8'] |
Tanto o VP9 quanto o VP8 oferecem suporte a Vídeo escalável, o que é essencial para sessões com muitos assinantes. O VP9 oferece melhor compressão, exigindo menos largura de banda para qualidade equivalente. O VP8 é a opção alternativa para terminais nos quais o vídeo escalável VP9 não está disponível (consulte o tabelas de cobertura de codecs). O H.264 com Scalable Video não é compatível com a plataforma; portanto, o H.264 deve ser evitado em sessões de grande porte, devendo-se utilizar o VP8 ou o VP9 em seu lugar. |
| Sessão pequena, dispositivos apenas com iOS | ['h264', 'vp8'] |
Os dispositivos iOS contam com aceleração de hardware para o H.264, o que reduz a carga sobre a CPU e aumenta a duração da bateria. O VP8 continua sendo uma opção alternativa segura. |
| Sessão pequena, com largura de banda limitada | ['vp9', 'vp8'] |
O VP9 oferece melhor qualidade do que o VP8 na mesma taxa de bits. O VP8 é a opção alternativa para dispositivos que não suportam o VP9 (por exemplo, versões mais antigas do Safari). |
| Editor de compartilhamento de tela | ['vp9', 'vp8'] |
O conteúdo da tela é compactado de forma muito eficiente com o VP9, devido ao seu excelente tratamento de bordas nítidas e regiões estáticas. O VP8 é a opção alternativa. |
| Compartilhamento de tela com a melhor compressão | ['vp9'] |
Dê preferência ao VP9 por seu desempenho superior no tratamento de bordas nítidas e regiões estáticas. Outros codecs compatíveis ainda são negociados com prioridade menor, servindo como alternativas. |
| Compatibilidade máxima (deve atingir todos os dispositivos) | ['vp8'] |
O VP8 é o único codec compatível com todos os terminais do OpenTok, incluindo o SDK para Linux (que não suporta H.264) e versões mais antigas do Safari (que podem não suportar VP9). |
Dica: Se nenhum dos cenários acima se aplicar ao seu caso de uso, considere usar modo automático em vez disso. Isso permite que o SDK escolha a melhor ordem com base no ambiente local e incorporará heurísticas aprimoradas em versões futuras.
Como funciona a negociação de codecs
Definir um codec preferencial faz não garantir que o codec será utilizado. O codec final é determinado por um processo de negociação que depende do tipo de sessão.
Sessões roteadas (Media Router)
Em um sessão encaminhada, o editor negocia com o OpenTok Media Router:
- O provedor envia uma oferta SDP com os codecs ordenados de acordo com a preferência (o codec preferido aparece em primeiro lugar).
- O Media Router analisa a oferta e seleciona um codec compatível.
- Se o codec preferencial for compatível, ele será utilizado. Caso contrário, o Media Router recorre ao próximo codec disponível na oferta.
Como o Media Router é responsável pela distribuição de mídia, todos os assinantes em uma sessão roteada recebem o vídeo codificado com o mesmo codec que o editor negociou.
Sessões retransmitidas (ponto a ponto)
Em um sessão retransmitida, não há um Media Router. Cada par emissor-destinatário negocia de forma independente:
- O provedor envia uma oferta SDP com os codecs ordenados por ordem de preferência.
- O assinante responde com uma resposta SDP que lista os codecs compatíveis.
- O par seleciona o codec de maior prioridade que ambos os terminais suportam.
Isso significa que diferentes pares de assinantes na mesma sessão retransmitida podem acabar usando codecs diferentes, dependendo das capacidades de cada assinante.
O que pode causar um fallback?
Um “fallback” significa que o codec preferencial não foi utilizado e que, em seu lugar, foi selecionado um codec diferente para a publicação. Isso pode ocorrer quando:
- O codec preferencial não é compatível com o terminal remoto (em sessões retransmitidas) ou com o Media Router (em sessões roteadas).
- O navegador ou dispositivo não suporta a codificação com o codec preferencial (por exemplo, H.264 em alguns dispositivos Android, VP9 em versões mais antigas do Safari).
Como podem ocorrer falhas, Verify sempre o codec em uso, em vez de presumir que a preferência foi respeitada. Saber qual é o codec ativo ajuda você a:
- Depurar e monitorar a qualidade. Registre qual codec está sendo usado para fins de diagnóstico e análise de qualidade por meio do Insights.
- Adaptar em tempo de execução. Ajuste as configurações de resolução ou taxa de bits com base nos pontos fortes do codec negociado (por exemplo, o VP9 pode atingir a mesma qualidade com uma taxa de bits menor do que o VP8).
- Garantir a consistência da sessão. Verifique se todos os emissores em uma sessão estão usando o codec esperado, especialmente em sessões roteadas, nas quais o Media Router distribui um único codec por emissor a todos os assinantes.
Veja Verificando o codec em uso para obter instruções específicas para cada plataforma.
Definição de preferências por plataforma
SDK da Web
export type VideoCodec = 'vp8' | 'vp9' | 'h264';
export type PreferredVideoCodecs = 'automatic' | [VideoCodec, ...VideoCodec[]];
// Automatic mode
const publisher = OT.initPublisher('publisherContainer', {
preferredVideoCodecs: 'automatic'
});
// Manual mode
const publisher = OT.initPublisher('publisherContainer', {
preferredVideoCodecs: ['vp9', 'vp8']
});
// Default (uses project-level preferred codec)
const publisher = OT.initPublisher('publisherContainer', {});
Passar um array vazio ou uma string de codec inválida faz com que o publisher falhe com um OT_INVALID_PARAMETER erro.
SDK do iOS
// Automatic mode
OTVideoCodecPreference *pref = [OTVideoCodecPreference automatic];
OTPublisherKitSettings *settings = [[OTPublisherKitSettings alloc] init];
settings.videoCodecPreference = pref;
OTPublisherKit *publisher = [[OTPublisherKit alloc] initWithDelegate:self
settings:settings];
// Manual mode
OTVideoCodecPreference *pref = [OTVideoCodecPreference manualWithCodecs:@[
@(OTVideoCodecTypeVP9),
@(OTVideoCodecTypeH264),
@(OTVideoCodecTypeVP8)
]];
OTPublisherKitSettings *settings = [[OTPublisherKitSettings alloc] init];
settings.videoCodecPreference = pref;
SDK do Android
// Automatic mode
PublisherKit.PreferredVideoCodecs preferredVideoCodecs =
PublisherKit.PreferredVideoCodecs.automatic();
Publisher publisher = new Publisher.Builder(context)
.preferredVideoCodecs(preferredVideoCodecs)
.build();
// Manual mode
PublisherKit.PreferredVideoCodecs preferredVideoCodecs =
PublisherKit.PreferredVideoCodecs.manual(
new ArrayList<PublisherKit.PreferredVideoCodecs.Codec>(
List.of(PublisherKit.PreferredVideoCodecs.Codec.VP9,
PublisherKit.PreferredVideoCodecs.Codec.H264)));
Publisher publisher = new Publisher.Builder(context)
.preferredVideoCodecs(preferredVideoCodecs)
.build();
Passando por um null ou lista vazia para manual() lança IllegalArgumentException.
SDK do Windows
// Automatic mode
builder.PreferredVideoCodecs = PreferredVideoCodecs.Automatic();
// Manual mode
builder.PreferredVideoCodecs = new PreferredVideoCodecs(
new List<PreferredVideoCodecs.Codec> {
PreferredVideoCodecs.Codec.VP9,
PreferredVideoCodecs.Codec.H264,
PreferredVideoCodecs.Codec.VP8
});
// Default (uses project-level setting)
builder.PreferredVideoCodecs = null;
Passar uma lista vazia gera uma exceção ArgumentException.
SDK do Linux
// Automatic mode
otc_publisher_settings* settings = otc_publisher_settings_new();
otc_publisher_settings_set_preferred_video_codecs_automatic(settings);
otc_publisher_callbacks callbacks = {0};
struct otc_publisher* publisher =
otc_publisher_new_with_settings(&callbacks, settings);
otc_publisher_settings_delete(settings);
// Manual mode
otc_publisher_settings* settings = otc_publisher_settings_new();
otc_video_codec_type codecs[] = {
OTC_VIDEO_CODEC_VP9,
OTC_VIDEO_CODEC_H264,
OTC_VIDEO_CODEC_VP8
};
otc_publisher_settings_set_preferred_video_codecs(
settings, codecs, sizeof(codecs) / sizeof(codecs[0]));
otc_publisher_callbacks callbacks = {0};
struct otc_publisher* publisher =
otc_publisher_new_with_settings(&callbacks, settings);
otc_publisher_settings_delete(settings);
SDK do React Native
// Automatic mode
<OTPublisher properties={{ preferredVideoCodecs: 'automatic' }} />
// Manual mode
<OTPublisher properties={{ preferredVideoCodecs: ['vp9', 'vp8'] }} />
Verificando o codec em uso
Depois que um provedor iniciar a transmissão, use as APIs de estatísticas do SDK para confirmar qual codec foi efetivamente negociado. Não presuma que a preferência foi respeitada.
Verificação dos codecs compatíveis antes da publicação
Você pode verificar antecipadamente quais codecs um cliente suporta antes de definir uma preferência.
SDK da Web:
const supportedCodecs = await OT.getSupportedCodecs();
console.log('Encoders:', supportedCodecs.videoEncoders);
console.log('Decoders:', supportedCodecs.videoDecoders);
SDK do Android:
MediaUtils.SupportedCodecs supported =
MediaUtils.SupportedCodecs.getSupportedCodecs(context);
Log.d("Codecs", "Encoders: " + supported.videoEncoders);
Log.d("Codecs", "Decoders: " + supported.videoDecoders);
SDK do Linux:
otc_media_utils_codecs* supported_codecs = NULL;
otc_status status = otc_media_utils_get_supported_codecs(&supported_codecs);
if (status == OTC_SUCCESS) {
for (size_t i = 0; i < supported_codecs->number_encoder_video_codecs; i++) {
printf("Encoder: %d\n", supported_codecs->encoder_video_codecs[i]);
}
for (size_t i = 0; i < supported_codecs->number_decoder_video_codecs; i++) {
printf("Decoder: %d\n", supported_codecs->decoder_video_codecs[i]);
}
otc_media_utils_codecs_delete(supported_codecs);
}
Lendo o codec ativo a partir das estatísticas do SDK
Observação: Para ler o codec ativo a partir das estatísticas do SDK, é necessário o Web SDK 2.33 ou posterior, versão que introduziu a API de Observabilidade do Cliente, a qual expõe informações sobre o codec no objeto stats.
SDK da Web
Editora:
setInterval(() => {
publisher.getStats((error, statsArray) => {
if (error) return;
statsArray.forEach(({ stats }) => {
if (stats.video && stats.video.layers) {
stats.video.layers.forEach((layer) => {
console.log('Publisher video codec:', layer.codec);
});
}
});
});
}, 5000);
Assinante:
setInterval(() => {
subscriber.getStats((error, stats) => {
if (error) return;
if (stats.video) {
console.log('Subscriber video codec:', stats.video.codec);
}
});
}, 5000);
Para obter informações mais detalhadas sobre o WebRTC, use getRtcStatsReport():
publisher.getRtcStatsReport()
.then(statsArray => {
// Each entry contains a standard RTCStatsReport.
// Look for type "codec" entries with mimeType.
statsArray.forEach(console.log);
});
SDK do Android
publisher.setNetworkStatsListener(new PublisherKit.NetworkStatsListener() {
@Override
public void onVideoStats(PublisherKit publisher,
PublisherKit.PublisherVideoStats[] statsArray) {
if (statsArray != null && statsArray.length > 0) {
for (PublisherKit.VideoLayerStats layer : statsArray[0].videoLayers) {
Log.d("Codec", "Publisher codec: " + layer.codec);
}
}
}
});
SDK do iOS
- (void)publisher:(OTPublisherKit *)publisher
videoNetworkStatsUpdated:(NSArray<OTPublisherKitVideoNetworkStats *> *)statsArray {
OTPublisherKitVideoNetworkStats *stats = statsArray.firstObject;
for (OTPublisherKitVideoLayerStats *layer in stats.videoLayers) {
NSLog(@"Publisher codec: %@", layer.codec ?: @"unknown");
}
}
SDK do React Native
// Publisher
OTPublisher.getRtcStatsReport();
// Subscriber
OTSubscriber.getRtcStatsReport(streamId);
Como usar o Insights e o Video Inspector
A ferramenta Video Inspector exibe o codec, a resolução e a taxa de quadros no módulo Métricas de Qualidade. Passe o mouse sobre qualquer ponto de uma linha traçada para ver o codec em uso naquele momento.
Você também pode filtrar as estatísticas de transmissão por codec em Perspectivas Consultas GraphQL:
{
project(projectId: YOUR_PROJECT_ID) {
sessionData {
sessions(start: START_TIME, end: END_TIME) {
resources {
streamStatsCollection(filters: { videoCodec: VP9 }) {
resources {
createdAt
videoBitrateKbps
}
}
}
}
}
}
}
Melhores práticas
-
Leve em consideração o tipo de sessão. Em sessões roteadas, todos os assinantes compartilham um único codec por emissor. Em sessões retransmitidas, cada par negocia de forma independente; assim, o mesmo emissor pode usar codecs diferentes com assinantes diferentes.
-
Alinhar as configurações por editor e por projeto. O codec preferencial no nível do projeto continua válido para editores que não definam sua própria preferência. Certifique-se de que ambos os níveis estejam consistentes para evitar surpresas.
-
Verifique a compatibilidade com codecs no cliente. Antes de definir uma preferência manualmente, use
OT.getSupportedCodecs()(Web) ouMediaUtils.SupportedCodecs(Android) para confirmar se o codec preferido está disponível localmente. -
Comece pelo modo automático. A menos que você tenha uma exigência específica em relação ao codec, use o modo automático e deixe que o SDK faça a escolha. Versões futuras do SDK irão aprimorar os critérios de seleção automática, e seu aplicativo se beneficiará disso sem a necessidade de alterações no código.
-
Verifique o codec negociado. Uso
getStats()ougetRtcStatsReport()para confirmar o codec assim que a publicação começar. -
Faça testes em todos os dispositivos de destino. A compatibilidade com codecs varia de acordo com os navegadores e as plataformas. Consulte o tabelas de cobertura de codecs Para mais detalhes. Teste sua configuração de preferências nos dispositivos que seus usuários realmente utilizam.