← Toutes les extensions

Extension native · Produit phare

KlugMedia

com.klug.media

AUCUN APM NÉCESSAIRE. Téléchargez et profitez-en. Impossible de faire plus simple.

Caméra, voix bidirectionnelle et annulation d’écho matérielle dans une seule session native, avec publication et réception H.264 et Opus via RTMP standard.

iOSAndroidmacOS En production À partir de €99 / an · Acheter

Vue d’ensemble

AIR ne fournit actuellement aucune implémentation à jour du streaming multimédia en temps réel. KlugMedia l’ajoute sous forme d’extension native. Caméra, microphone, encodeur et annulation d’écho s’exécutent ensemble dans une seule session native, et ActionScript se contente d’envoyer des commandes et de recevoir des états.

La vidéo est publiée et reçue en H.264, la voix en Opus, le tout via RTMP standard. La vidéo reçue est dessinée nativement au-dessus de la scène AIR : elle reste donc nette et fluide, même sur des appareils plus anciens.

KlugMedia est utilisé chaque jour dans nos applications, notre preuve de concept, sur l’App Store, Google Play et le Mac.

Fonctionnalités

  • Autonome : une seule ANE, sans bibliothèque centrale ni ANE de dépendance à ajouter
  • Capture caméra et publication H.264 dans une seule session native
  • Réception et affichage H.264 natifs, au bon rapport d’aspect, avec recadrage-remplissage et rotation
  • Voix Opus bidirectionnelle avec annulation d’écho matérielle, les deux côtés pouvant parler en même temps
  • Aperçu caméra natif, changement de caméra, lampe torche et zoom
  • Instantanés pris directement depuis l’image de la caméra
  • Enregistrement MP4 des flux en direct sur le Klug Streaming Server, image et son
  • Adaptation automatique du débit sur les réseaux faibles
  • Tampon vocal adaptatif qui encaisse les micro-coupures du Wi-Fi et revient seul à un faible délai
  • Sur Mac : passage de la caméra intégrée aux caméras USB en environ une seconde
  • RTMP standard, donc compatible avec les serveurs multimédias ordinaires

Serveur de streaming

KlugMedia est fourni avec un logiciel serveur adapté, développé en même temps que l’extension et optimisé pour les applications AIR : gestion des flux, reconnexions fiables, relais de la voix bidirectionnelle, enregistrement MP4 et visionnage en direct dans un navigateur web.

Le serveur est décrit sur la page de présentation : Serveur de streaming.

Plateformes prises en charge

iOS arm64
Android arm64 · armv7
macOS Apple silicon · Intel
Applications iPad sur Mac Apple silicon · macOS 26 et 27

Applications iPad sur Mac

Sur les Mac Apple silicon, le build iOS d’une application AIR peut s’exécuter comme application iPad. KlugMedia prend en charge ce mode avec caméra, vidéo en direct et voix bidirectionnelle, y compris la caméra FaceTime intégrée et les caméras USB externes. Un seul build pour iPhone, iPad et Mac.

Prêt pour iOS 27 et macOS 27

KlugMedia est testé sur iOS 27, iPadOS 27 et macOS 27, sur iPhone, iPad, MacBook et Mac mini, ainsi que toujours sur iOS 17. Points forts de cette version :

  • Chemin de réception renforcé : arrêter et relancer un flux en direct est sûr à tout moment, y compris avec le minutage d’iOS 27
  • Aperçu caméra stable sur macOS 27 pour les applications iPad sur Mac, pendant que la caméra démarre, s’arrête ou change
  • Orientation correcte sur chaque Mac : les caméras intégrées et USB s’affichent à l’endroit dans l’aperçu et chez le récepteur, sur macOS 26 et 27
  • Changement de caméra rapide sur Mac entre la caméra FaceTime et les caméras USB, en environ une seconde
  • Voix claire sur le Wi-Fi des portables : un tampon adaptatif absorbe les brèves rafales Wi-Fi typiques des MacBook et se réduit à nouveau quand le réseau est calme

Prise en main

Ajoutez l’extension au descripteur de votre application :

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

Demandez l’autorisation d’accès à la caméra et au microphone avant le premier démarrage. L’extension prend alors en charge la capture : n’ouvrez pas en même temps une Camera ou un Microphone AIR.

Exemples de code

Cinq flux complets, tirés de l’API qui tourne chaque jour dans nos applications. Chaque appel retourne immédiatement ; les résultats arrivent sous forme de StatusEvents. Documentation complète →

1 · Publier un flux caméra
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 · Recevoir et suivre la mise en page
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 · Voix bidirectionnelle avec annulation d’écho
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 );
}
Les paquets vocaux circulent sous forme de messages de données sur leur propre paire de flux. Le serveur de streaming Klug les relaie d’office ; les autres serveurs RTMP doivent transmettre NetStream.send aux abonnés.
4 · Aperçu, changement de caméra, lampe torche, zoom, instantané
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 · Arrêt et redémarrage propres
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" );

Aperçu de l’API

isSupportedVrai là où la session multimédia native est disponible.
startPublish(…)Démarre la caméra et publie en H.264 via RTMP : taille, fps, débit, intervalle d’images clés, caméra, identifiants RTMP facultatifs.
stopPublish()Arrête la publication ; la caméra est libérée, sauf si l’aperçu est encore affiché.
startReceive(…)Lit nativement un flux distant dans un rectangle de la scène : ajustement au rapport d’aspect ou recadrage-remplissage avec rotation (étirement sur Android).
setReceiveFrame(x, y, w, h)Déplace et redimensionne la vidéo native, pour la rotation, les téléphones pliables et le plein écran.
stopReceive()Arrête la lecture et supprime la vue native.
showPreview(…) / hidePreview()Aperçu caméra natif au-dessus de la scène, seul ou à côté d’une publication en direct.
switchCamera()Passe à la caméra suivante pendant la diffusion : avant et arrière sur iPhone et iPad, caméras intégrée et USB sur Mac.
setTorch(on) / hasTorchLampe de la caméra pendant la diffusion, et indication de sa présence sur l’appareil.
setCameraZoom(step)Véritable zoom caméra sur iOS et Android, de 0 à 8 pour 1,0x à 2,0x ; le flux est lui aussi zoomé.
setVideoBitrate(kbps)Modifie le débit de l’encodeur en direct.
captureSnapshot(w, h)Enregistre un JPEG à partir de l’image de la caméra en direct.
isiOSAppOnMacVrai lorsque le build iOS s’exécute comme application iPad sur un Mac Apple silicon.
OpusVoiceBridgeVoix bidirectionnelle : démarrage, arrêt, annulation d’écho, haut-parleur, gain, tampon de lecture.
Red5OpusTransportTransporte les paquets Opus sur votre connexion RTMP, via deux flux dédiés.

Événements d’état

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

Acheter KlugMedia

Une licence annuelle pour une application AIR, avec toutes les mises à jour pendant 12 mois. Après le paiement, vous recevez l’extension, la bibliothèque ActionScript et la documentation par e-mail, généralement sous un jour ouvré. Licence et conditions

Simple
€99 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Sans support
Acheter Simple
Standard
€349 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Réponse par e-mail sous 7 jours
Acheter Standard
Priority
€699 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Réponse par e-mail sous 48 heures
Acheter Priority
Les taxes sont calculées lors du paiement par Link (Stripe). Vous saisissez l’identifiant d’application de votre app AIR pendant le paiement.

Prérequis

SDK AIR51.x (HARMAN)
iOSiOS 17 ou version ultérieure
AndroidAndroid 6.0 (API 23) ou version ultérieure
macOSmacOS 11 ou version ultérieure
Applications iPad sur MacApple silicon, macOS 26 ou version ultérieure
AutorisationsCaméra et microphone
ServeurTout serveur RTMP ; le serveur de streaming Klug correspondant est recommandé