Oversikt
AIR har for øyeblikket ingen oppdatert implementasjon for sanntidsstrømming av media. KlugMedia legger den til som en native utvidelse. Kamera, mikrofon, koder og ekkokansellering kjører sammen i én native økt, og ActionScript sender bare kommandoer og mottar status.
Video publiseres og mottas som H.264, tale som Opus, begge over standard RTMP. Mottatt video tegnes native oppå AIR-scenen, slik at den forblir skarp og jevn selv på eldre enheter.
KlugMedia brukes daglig i appene våre, vårt proof of concept, på App Store, Google Play og Mac.
Funksjoner
- Selvstendig: én ANE, ingen kjernebibliotek eller avhengige ANE-er å legge til
- Kameraopptak og H.264-publisering i én native økt
- Native H.264-mottak og -visning, riktig bildeformat, med utfylling ved beskjæring og rotasjon
- Toveis Opus-tale med maskinvarebasert ekkokansellering, begge sider snakker samtidig
- Native kameraforhåndsvisning, kamerabytte, lommelykt og zoom
- Øyeblikksbilder tatt direkte fra kamerabildet
- MP4-opptak av live-strømmer på Klug-streamingserveren, bilde og lyd
- Automatisk tilpasning av bitrate på svake nettverk
- Adaptiv talebuffer som jevner ut Wi-Fi-hikk og går tilbake til lav forsinkelse av seg selv
- På Mac: bytt mellom innebygd kamera og USB-kameraer på omtrent ett sekund
- Standard RTMP, så den fungerer med vanlige medieservere
Streamingserver
KlugMedia leveres med tilhørende serverprogramvare, utviklet sammen med utvidelsen og tilpasset AIR-apper: strømhåndtering, pålitelig gjentilkobling, toveis taleformidling, MP4-opptak og live-visning i en nettleser.
Støttede plattformer
iPad-apper på Mac
På Mac-er med Apple silicon kan iOS-bygget av en AIR-app kjøre som en iPad-app. KlugMedia støtter denne modusen med kamera, live video og toveis tale, inkludert det innebygde FaceTime-kameraet og eksterne USB-kameraer. Ett bygg dekker iPhone, iPad og Mac.
Klar for iOS 27 og macOS 27
KlugMedia er testet på iOS 27, iPadOS 27 og macOS 27, på iPhone, iPad, MacBook og Mac mini, og fortsatt på iOS 17. Høydepunkter i denne utgivelsen:
- Herdet mottakssti: det er trygt å stoppe og starte en live-strøm på nytt når som helst, også med timingen i iOS 27
- Stabil kameraforhåndsvisning på macOS 27 for iPad-apper på Mac, mens kameraet starter, stopper eller byttes
- Riktig orientering på alle Mac-er: innebygde og USB-kameraer står oppreist i forhåndsvisningen og hos mottakeren, på macOS 26 og 27
- Raskt kamerabytte på Mac mellom FaceTime-kameraet og USB-kameraer, på omtrent ett sekund
- Klar tale på Wi-Fi i bærbare: en adaptiv buffer tar opp de korte Wi-Fi-byene som er typiske for MacBook-er, og krymper tilbake når nettverket er rolig
Kom i gang
Legg utvidelsen til i applikasjonsbeskrivelsen din:
<extensions>
<extensionID>com.klug.media</extensionID>
</extensions>
Be om kamera- og mikrofontillatelse før første start. Utvidelsen eier deretter opptaket: ikke åpne et AIR-Camera eller -Microphone samtidig.
Kodeeksempler
Fem komplette flyter, hentet fra API-et som kjører i appene våre hver dag. Hvert kall returnerer med en gang; resultatene kommer som StatusEvents. Full dokumentasjon →
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(); }
// 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 ); });
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 ); }
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
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" );
API-oversikt
| isSupported | True der den native medieøkten er tilgjengelig. |
| startPublish(…) | Starter kameraet og publiserer H.264 over RTMP: størrelse, fps, bitrate, nøkkelbildeintervall, kamera, valgfri RTMP-innlogging. |
| stopPublish() | Stopper publiseringen; kameraet frigis med mindre forhåndsvisningen fortsatt vises. |
| startReceive(…) | Spiller av en ekstern strøm native inne i et rektangel på scenen: tilpass bildeformat eller fyll med beskjæring og rotasjon (strekk på Android). |
| setReceiveFrame(x, y, w, h) | Flytter og endrer størrelsen på den native videoen, for rotasjon, sammenleggbare telefoner og fullskjerm. |
| stopReceive() | Stopper avspillingen og fjerner den native visningen. |
| showPreview(…) / hidePreview() | Native kameraforhåndsvisning over scenen, alene eller ved siden av en live publisering. |
| switchCamera() | Bytter til neste kamera under strømming: foran og bak på iPhone og iPad, innebygde og USB-kameraer på Mac. |
| setTorch(on) / hasTorch | Kameralys under strømming, og om enheten har et. |
| setCameraZoom(step) | Ekte kamerazoom på iOS og Android, 0..8 for 1,0x til 2,0x; strømmen zoomes også. |
| setVideoBitrate(kbps) | Endrer koderens bitrate mens det går live. |
| captureSnapshot(w, h) | Lagrer en JPEG fra det levende kamerabildet. |
| isiOSAppOnMac | True når iOS-bygget kjører som en iPad-app på en Mac med Apple silicon. |
| OpusVoiceBridge | Toveis tale: start, stopp, ekkokansellering, høyttaler, forsterkning, avspillingsbuffer. |
| Red5OpusTransport | Fører Opus-pakkene over RTMP-forbindelsen din på to dedikerte strømmer. |
Statushendelser
| cameraStatus | connecting · connected · disconnected · failed:<reason> · authError:<reason> · newBitrate:<rate> · authSuccess (Android) |
| receiveStatus | playing · firstFrame · disconnected · streamEnded og failed:<reason> (iOS, macOS) |
| snapshotStatus | saved:<path> · failed:<reason> |
Kjøp KlugMedia
En årslisens for én AIR-applikasjon, med alle oppdateringer i 12 måneder. Etter betaling mottar du utvidelsen, ActionScript-biblioteket og dokumentasjonen på e-post, vanligvis innen én virkedag. Lisens og vilkår
- Lisens for én AIR-applikasjon
- Alle oppdateringer i 12 måneder
- Ingen støtte
- Lisens for én AIR-applikasjon
- Alle oppdateringer i 12 måneder
- Svar på e-post innen 7 dager
- Lisens for én AIR-applikasjon
- Alle oppdateringer i 12 måneder
- Svar på e-post innen 48 timer
Krav
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 17 eller nyere |
| Android | Android 6.0 (API 23) eller nyere |
| macOS | macOS 11 eller nyere |
| iPad-apper på Mac | Apple silicon, macOS 26 eller nyere |
| Tillatelser | Kamera og mikrofon |
| Server | Hvilken som helst RTMP-server; den tilhørende Klug-streamingserveren anbefales |