← Todas as extensões

Extensão nativa · Carro-chefe

KlugMedia

com.klug.media

NÃO É NECESSÁRIO APM. Baixe e aproveite. Não tem como ser mais simples.

Câmera, voz bidirecional e cancelamento de eco por hardware em uma única sessão nativa, publicando e recebendo H.264 e Opus sobre RTMP padrão.

iOSAndroidmacOS Em produção A partir de €99 / ano · Comprar

Visão geral

Atualmente, o AIR não oferece uma implementação atualizada para streaming de mídia em tempo real. O KlugMedia a adiciona como extensão nativa. Câmera, microfone, encoder e cancelamento de eco rodam juntos em uma única sessão nativa, e o ActionScript apenas envia comandos e recebe status.

O vídeo é publicado e recebido em H.264, a voz em Opus, ambos sobre RTMP padrão. O vídeo recebido é desenhado nativamente sobre o palco do AIR, por isso continua nítido e fluido mesmo em dispositivos mais antigos.

O KlugMedia é usado diariamente em nossos apps, nossa prova de conceito, na App Store, no Google Play e no Mac.

Recursos

  • Autossuficiente: uma ANE, sem biblioteca principal nem ANEs de dependência para adicionar
  • Captura de câmera e publicação em H.264 em uma única sessão nativa
  • Recepção e exibição nativas de H.264, com proporção correta, preenchimento com corte e rotação
  • Voz Opus bidirecional com cancelamento de eco por hardware, com os dois lados falando ao mesmo tempo
  • Prévia nativa da câmera, troca de câmera, lanterna e zoom
  • Fotos capturadas direto da imagem da câmera
  • Gravação em MP4 de streams ao vivo no servidor de streaming da Klug, imagem e som
  • Adaptação automática de bitrate em redes fracas
  • Buffer de voz adaptativo que supera as oscilações do Wi-Fi e volta sozinho a um atraso baixo
  • No Mac: alterne entre a câmera integrada e câmeras USB em cerca de um segundo
  • RTMP padrão, por isso funciona com servidores de mídia comuns

Servidor de streaming

O KlugMedia acompanha software de servidor compatível, desenvolvido junto com a extensão e ajustado para apps AIR: gerenciamento de streams, reconexões confiáveis, retransmissão de voz bidirecional, gravação em MP4 e visualização ao vivo em um navegador web.

O servidor é descrito na página de visão geral: Servidor de streaming.

Plataformas compatíveis

iOS arm64
Android arm64 · armv7
macOS Apple silicon · Intel
Apps iPad no Mac Apple silicon · macOS 26 e 27

Apps iPad no Mac

Em Macs com Apple silicon, o build iOS de um app AIR pode rodar como app iPad. O KlugMedia oferece suporte a esse modo com câmera, vídeo ao vivo e voz bidirecional, incluindo a câmera FaceTime integrada e câmeras USB externas. Um único build atende iPhone, iPad e Mac.

Pronto para iOS 27 e macOS 27

O KlugMedia é testado no iOS 27, iPadOS 27 e macOS 27, em iPhone, iPad, MacBook e Mac mini, e também ainda no iOS 17. Destaques desta versão:

  • Caminho de recepção reforçado: parar e reiniciar um stream ao vivo é seguro a qualquer momento, inclusive com o timing do iOS 27
  • Prévia de câmera estável no macOS 27 para apps iPad no Mac, enquanto a câmera inicia, para ou troca
  • Orientação correta em todo Mac: câmeras integradas e USB aparecem na posição correta na prévia e no receptor, no macOS 26 e 27
  • Troca rápida de câmera no Mac entre a câmera FaceTime e câmeras USB, em cerca de um segundo
  • Voz nítida no Wi-Fi de notebooks: um buffer adaptativo absorve as rajadas curtas de Wi-Fi típicas de MacBooks e volta a diminuir quando a rede está calma

Primeiros passos

Adicione a extensão ao descritor do seu aplicativo:

app.xml
<extensions>
    <extensionID>com.klug.media</extensionID>
</extensions>

Solicite a permissão de câmera e microfone antes da primeira inicialização. A extensão passa então a controlar a captura: não abra uma Camera ou um Microphone do AIR ao mesmo tempo.

Exemplos de código

Cinco fluxos completos, extraídos da API que roda em nossos apps todos os dias. Cada chamada retorna imediatamente; os resultados chegam como StatusEvents. Documentação completa →

1 · Publicar um stream de câmera
Station.as
import com.klug.petcam.camera.CameraStreamANE;
import flash.events.StatusEvent;

var media:CameraStreamANE = CameraStreamANE.instance;
media.addEventListener( StatusEvent.STATUS, onMedia );

if ( media.isSupported )
{
    // camera, H.264 encoder and RTMP in one native session
    media.startPublish( "rtmp://your.server:1935/live", "station-1",
                        640, 480,     // size
                        12, 800,      // fps, kbps
                        2,            // keyframe every 2 s: fast start at the viewer
                        CameraStreamANE.CAMERA_BACK );
}

function onMedia( e:StatusEvent ):void
{
    if ( e.code != CameraStreamANE.STATUS_EVENT ) return;
    if ( e.level == "connected" )             showLive();
    else if ( e.level.indexOf( "failed:" ) == 0 )  retryLater( e.level.substr( 7 ) );
    else if ( e.level.indexOf( "authError:" ) == 0 ) askForLogin();
}
2 · Receber e acompanhar o layout
Viewer.as
// the video is decoded natively and drawn in a view above the stage (pixels)
media.startReceive( "rtmp://your.server:1935/live", "station-1",
                    0, 80, stage.stageWidth, stage.stageHeight - 160,
                    0, CameraStreamANE.RECEIVE_FIT );   // or RECEIVE_CROPFILL

media.addEventListener( StatusEvent.STATUS, function( e:StatusEvent ):void {
    if ( e.code == "receiveStatus" && e.level == "firstFrame" ) hideSpinner();
});

// rotation, a folding phone, fullscreen: move the native view with the stage
stage.addEventListener( Event.RESIZE, function( e:Event ):void {
    media.setReceiveFrame( 0, 80, stage.stageWidth, stage.stageHeight - 160 );
});
3 · Voz bidirecional com cancelamento de eco
Voice.as
import com.klug.petcam.audioecho.*;

var voice:OpusVoiceBridge = new OpusVoiceBridge( new NativeOpusCodec(), 48000, 1, 960 );
var link:Red5OpusTransport;

var nc:NetConnection = new NetConnection();
nc.addEventListener( NetStatusEvent.NET_STATUS, function( e:NetStatusEvent ):void {
    if ( e.info.code == "NetConnection.Connect.Success" ) startVoice();
});
nc.connect( "rtmp://your.server:1935/live" );

function startVoice():void
{
    link = new Red5OpusTransport( nc );
    link.addEventListener( OpusPacketEvent.PACKET, function( e:OpusPacketEvent ):void {
        voice.playRemoteOpus( e.packet );            // decode and play the other side
    });
    link.start( "voice_me", "voice_other" );     // my stream, the other side's stream

    voice.setVoiceProcessing( true );             // hardware echo cancellation
    EchoCancellationANE.instance.setDuck( false ); // both sides may talk at once
    voice.start();
    addEventListener( Event.ENTER_FRAME, sendVoice );
}

function sendVoice( e:Event ):void
{
    var packet:ByteArray;
    while ( ( packet = voice.readLocalOpus() ) != null )   // every finished 20 ms frame
        link.sendPacket( packet );
}
Os pacotes de voz trafegam como mensagens de dados em seu próprio par de streams. O servidor de streaming da Klug os retransmite sem configuração adicional; outros servidores RTMP precisam encaminhar NetStream.send aos assinantes.
4 · Prévia, troca de câmera, lanterna, zoom, foto
Controls.as
media.showPreview( 20, 100, 320, 240, CameraStreamANE.CAMERA_FRONT );   // aiming preview

media.switchCamera();               // front / back, or built-in / USB camera on the Mac
if ( media.hasTorch ) media.setTorch( true );
media.setCameraZoom( 4 );           // 0..8 = 1.0x..2.0x, the stream is zoomed too
media.setVideoBitrate( 500 );       // change the bitrate while live

media.addEventListener( StatusEvent.STATUS, function( e:StatusEvent ):void {
    if ( e.code == "snapshotStatus" && e.level.indexOf( "saved:" ) == 0 )
        showPhoto( e.level.substr( 6 ) );                // absolute path of the JPEG
});
media.captureSnapshot( 640, 480 );

media.hidePreview();   // native views sit above the stage: hide them before dialogs
5 · Parada limpa e reinício
Session.as
function stopAll():void
{
    removeEventListener( Event.ENTER_FRAME, sendVoice );
    voice.stop();
    link.stop();
    media.stopReceive();
    media.stopPublish();    // always stop before publishing the same name again
}

// safe at any moment, also while a stream is still connecting
stopAll();
media.startPublish( "rtmp://your.server:1935/live", "station-1" );

Visão geral da API

isSupportedVerdadeiro onde a sessão de mídia nativa está disponível.
startPublish(…)Inicia a câmera e publica H.264 sobre RTMP: tamanho, fps, bitrate, intervalo de keyframes, câmera, login RTMP opcional.
stopPublish()Interrompe a publicação; a câmera é liberada, a menos que a prévia ainda esteja sendo exibida.
startReceive(…)Reproduz um stream remoto nativamente dentro de um retângulo do palco: ajuste proporcional ou preenchimento com corte e rotação (esticado no Android).
setReceiveFrame(x, y, w, h)Move e redimensiona o vídeo nativo, para rotação, celulares dobráveis e tela cheia.
stopReceive()Interrompe a reprodução e remove a view nativa.
showPreview(…) / hidePreview()Prévia nativa da câmera sobre o palco, isolada ou junto de uma publicação ao vivo.
switchCamera()Alterna para a próxima câmera durante o streaming: frontal e traseira no iPhone e iPad, câmeras integradas e USB no Mac.
setTorch(on) / hasTorchLuz da câmera durante o streaming, e se o dispositivo tem uma.
setCameraZoom(step)Zoom real da câmera no iOS e Android, 0..8 para 1.0x a 2.0x; o stream também recebe o zoom.
setVideoBitrate(kbps)Altera o bitrate do encoder durante a transmissão ao vivo.
captureSnapshot(w, h)Salva um JPEG da imagem ao vivo da câmera.
isiOSAppOnMacVerdadeiro quando o build iOS roda como app iPad em um Mac com Apple silicon.
OpusVoiceBridgeVoz bidirecional: iniciar, parar, cancelamento de eco, alto-falante, ganho, buffer de reprodução.
Red5OpusTransportTransporta os pacotes Opus pela sua conexão RTMP em dois streams dedicados.

Eventos de status

cameraStatusconnecting · connected · disconnected · failed:<reason> · authError:<reason> · newBitrate:<rate> · authSuccess (Android)
receiveStatusplaying · firstFrame · disconnected · streamEnded e failed:<reason> (iOS, macOS)
snapshotStatussaved:<path> · failed:<reason>

Compre o KlugMedia

Uma licença anual para um app AIR, com todas as atualizações por 12 meses. Após o pagamento, você recebe a extensão, a biblioteca ActionScript e a documentação por e-mail, normalmente em até um dia útil. Licença e termos

Simples
€99 / ano
  • Licença para um app AIR
  • Todas as atualizações por 12 meses
  • Sem suporte
Comprar Simples
Padrão
€349 / ano
  • Licença para um app AIR
  • Todas as atualizações por 12 meses
  • Resposta por e-mail em até 7 dias
Comprar Padrão
Prioritário
€699 / ano
  • Licença para um app AIR
  • Todas as atualizações por 12 meses
  • Resposta por e-mail em até 48 horas
Comprar Prioritário
Os impostos são calculados no checkout pelo Link (Stripe). Você informa o ID do aplicativo do seu app AIR durante o checkout.

Requisitos

AIR SDK51.x (HARMAN)
iOSiOS 17 ou posterior
AndroidAndroid 6.0 (API 23) ou posterior
macOSmacOS 11 ou posterior
Apps iPad no MacApple silicon, macOS 26 ou posterior
PermissõesCâmera e microfone
ServidorQualquer servidor RTMP; recomendamos o servidor de streaming da Klug compatível