Yleiskatsaus
AIR ei tällä hetkellä tarjoa ajantasaista toteutusta reaaliaikaiseen mediastriimaukseen. KlugMedia lisää sen natiivilaajennuksena. Kamera, mikrofoni, enkooderi ja kaiunpoisto toimivat yhdessä yhdessä natiivissa istunnossa, ja ActionScript vain lähettää komentoja ja vastaanottaa tilatietoja.
Video julkaistaan ja vastaanotetaan H.264:nä ja ääni Opusina, molemmat tavallisella RTMP:llä. Vastaanotettu video piirretään natiivisti AIR-näyttämön päälle, joten se pysyy terävänä ja sujuvana myös vanhemmilla laitteilla.
KlugMedia on päivittäisessä käytössä sovelluksissamme, todisteenamme toimivuudesta, App Storessa, Google Playssa ja Macilla.
Ominaisuudet
- Itsenäinen: yksi ANE, ei ydinkirjastoa tai riippuvaisia ANE-laajennuksia lisättäväksi
- Kameran kuvaus ja H.264-julkaisu yhdessä natiivissa istunnossa
- Natiivi H.264-vastaanotto ja -toisto, kuvasuhde säilyttäen, täyttöleikkauksella ja kierrolla
- Kaksisuuntainen Opus-ääni laitteistopohjaisella kaiunpoistolla, molemmat osapuolet voivat puhua yhtä aikaa
- Natiivi kameran esikatselu, kameran vaihto, kameran valo ja zoomaus
- Kuvakaappaukset suoraan kameran kuvasta
- Live-striimien MP4-tallennus Klugin suoratoistopalvelimella, kuva ja ääni
- Automaattinen bittinopeuden mukautus heikoilla verkoilla
- Mukautuva äänipuskuri, joka selviää Wi-Fi-katkoksista ja palaa itsestään pieneen viiveeseen
- Macilla: vaihda sisäänrakennetun kameran ja USB-kameroiden välillä noin sekunnissa
- Tavallinen RTMP, joten se toimii tavallisten mediapalvelinten kanssa
Suoratoistopalvelin
KlugMedian mukana tulee sopiva palvelinohjelmisto, joka on kehitetty yhdessä laajennuksen kanssa ja viritetty AIR-sovelluksille: striimien hallinta, luotettava uudelleenyhdistäminen, kaksisuuntaisen äänen välitys, MP4-tallennus ja live-katselu verkkoselaimessa.
Tuetut alustat
iPad-sovellukset Macilla
Apple silicon -Maceilla AIR-sovelluksen iOS-versio voi toimia iPad-sovelluksena. KlugMedia tukee tätä tilaa kameralla, live-videolla ja kaksisuuntaisella äänellä, mukaan lukien sisäänrakennettu FaceTime-kamera ja ulkoiset USB-kamerat. Yksi versio palvelee iPhonea, iPadia ja Macia.
Valmis iOS 27:lle ja macOS 27:lle
KlugMedia on testattu iOS 27:llä, iPadOS 27:llä ja macOS 27:llä, iPhonella, iPadilla, MacBookilla ja Mac minillä, sekä edelleen iOS 17:llä. Tämän julkaisun kohokohdat:
- Vahvistettu vastaanottopolku: live-striimin pysäyttäminen ja uudelleenkäynnistys on turvallista milloin tahansa, myös iOS 27:n ajoituksella
- Vakaa kameran esikatselu macOS 27:llä iPad-sovelluksille Macilla, kun kamera käynnistyy, pysähtyy tai vaihtuu
- Oikea suunta jokaisella Macilla: sisäänrakennetut ja USB-kamerat näkyvät pystyssä esikatselussa ja vastaanottajalla, macOS 26:lla ja 27:llä
- Nopea kameran vaihto Macilla FaceTime-kameran ja USB-kameroiden välillä, noin sekunnissa
- Selkeä ääni kannettavan Wi-Fi-yhteydellä: mukautuva puskuri vaimentaa MacBookeille tyypilliset lyhyet Wi-Fi-purskeet ja pienenee takaisin, kun verkko on rauhallinen
Aloitus
Lisää laajennus sovelluksesi descriptoriin:
<extensions>
<extensionID>com.klug.media</extensionID>
</extensions>
Pyydä kamera- ja mikrofonilupa ennen ensimmäistä käynnistystä. Laajennus omistaa tämän jälkeen kuvauksen: älä avaa AIR-Camera- tai -Microphone-oliota samanaikaisesti.
Koodiesimerkit
Viisi täydellistä esimerkkiä sovelluksissamme päivittäin pyörivästä rajapinnasta. Jokainen kutsu palaa heti; tulokset saapuvat StatusEvent-tapahtumina. Koko dokumentaatio →
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" );
Rajapintayleiskatsaus
| isSupported | True siellä, missä natiivi mediaistunto on käytettävissä. |
| startPublish(…) | Käynnistää kameran ja julkaisee H.264:n RTMP:llä: koko, fps, bittinopeus, avainkehysväli, kamera, valinnainen RTMP-kirjautuminen. |
| stopPublish() | Pysäyttää julkaisun; kamera vapautetaan, ellei esikatselua vielä näytetä. |
| startReceive(…) | Toistaa etästriimin natiivisti näyttämön suorakulmion sisällä: kuvasuhteen mukaan sovitettuna tai täyttöleikattuna kierrolla (Androidilla venytys). |
| setReceiveFrame(x, y, w, h) | Siirtää ja skaalaa natiivivideon, kiertoa, taittuvia puhelimia ja koko näyttöä varten. |
| stopReceive() | Pysäyttää toiston ja poistaa natiivinäkymän. |
| showPreview(…) / hidePreview() | Natiivi kameran esikatselu näyttämön päällä, yksin tai live-julkaisun rinnalla. |
| switchCamera() | Vaihtaa seuraavaan kameraan striimauksen aikana: etu- ja takakamera iPhonella ja iPadilla, sisäänrakennettu ja USB-kamerat Macilla. |
| setTorch(on) / hasTorch | Kameran valo striimauksen aikana ja tieto siitä, onko laitteessa sellaista. |
| setCameraZoom(step) | Todellinen kameran zoomaus iOS:llä ja Androidilla, 0..8 vastaa 1,0x–2,0x; striimi zoomataan myös. |
| setVideoBitrate(kbps) | Muuttaa enkooderin bittinopeutta livenä. |
| captureSnapshot(w, h) | Tallentaa JPEG-kuvan kameran live-kuvasta. |
| isiOSAppOnMac | True, kun iOS-versio toimii iPad-sovelluksena Apple silicon -Macilla. |
| OpusVoiceBridge | Kaksisuuntainen ääni: käynnistys, pysäytys, kaiunpoisto, kaiutin, vahvistus, toistopuskuri. |
| Red5OpusTransport | Kuljettaa Opus-paketit RTMP-yhteytesi yli kahdella omalla striimillä. |
Tilatapahtumat
| cameraStatus | connecting · connected · disconnected · failed:<reason> · authError:<reason> · newBitrate:<rate> · authSuccess (Android) |
| receiveStatus | playing · firstFrame · disconnected · streamEnded ja failed:<reason> (iOS, macOS) |
| snapshotStatus | saved:<path> · failed:<reason> |
Osta KlugMedia
Vuosilisenssi yhdelle AIR-sovellukselle, kaikki päivitykset 12 kuukauden ajan. Maksun jälkeen saat laajennuksen, ActionScript-kirjaston ja dokumentaation sähköpostitse, yleensä yhden arkipäivän kuluessa. Lisenssi ja ehdot
- Lisenssi yhdelle AIR-sovellukselle
- Kaikki päivitykset 12 kuukauden ajan
- Ei tukea
- Lisenssi yhdelle AIR-sovellukselle
- Kaikki päivitykset 12 kuukauden ajan
- Vastaus sähköpostitse 7 päivän kuluessa
- Lisenssi yhdelle AIR-sovellukselle
- Kaikki päivitykset 12 kuukauden ajan
- Vastaus sähköpostitse 48 tunnin kuluessa
Vaatimukset
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 17 tai uudempi |
| Android | Android 6.0 (API 23) tai uudempi |
| macOS | macOS 11 tai uudempi |
| iPad-sovellukset Macilla | Apple silicon, macOS 26 tai uudempi |
| Oikeudet | Kamera ja mikrofoni |
| Palvelin | Mikä tahansa RTMP-palvelin; suositeltavaa on sopiva Klugin suoratoistopalvelin |