← Все расширения

Нативное расширение · Флагман

KlugMedia

com.klug.media

APM НЕ НУЖЕН. Скачайте и пользуйтесь. Проще уже некуда.

Камера, двусторонняя голосовая связь и аппаратное эхоподавление в одной нативной сессии; публикация и приём H.264 и Opus по стандартному RTMP.

iOSAndroidmacOS В продакшене От €99 / год · Купить

Обзор

В AIR сейчас нет актуальной реализации потоковой передачи медиа в реальном времени. KlugMedia добавляет её как нативное расширение. Камера, микрофон, кодировщик и эхоподавление работают вместе в одной нативной сессии, а ActionScript только отправляет команды и получает статус.

Видео публикуется и принимается как H.264, голос — как Opus, оба по стандартному RTMP. Принятое видео рисуется нативно поверх сцены AIR, поэтому остаётся чётким и плавным даже на старых устройствах.

KlugMedia ежедневно используется в наших приложениях, нашем доказательстве работоспособности, в App Store, Google Play и на Mac.

Возможности

  • Автономность: один ANE, без базовой библиотеки и зависимых ANE
  • Захват с камеры и публикация H.264 в одной нативной сессии
  • Нативный приём и отображение H.264 с сохранением пропорций, с обрезкой по размеру и поворотом
  • Двусторонний голос Opus с аппаратным эхоподавлением, обе стороны говорят одновременно
  • Нативный предпросмотр камеры, переключение камеры, фонарик и зум
  • Снимки прямо из изображения камеры
  • Запись MP4 живых потоков на стриминг-сервере Klug, изображение и звук
  • Автоматическая адаптация битрейта в слабых сетях
  • Адаптивный буфер голоса, который переживает сбои Wi-Fi и сам возвращается к малой задержке
  • На Mac: переключение между встроенной камерой и USB-камерами примерно за секунду
  • Стандартный RTMP, поэтому работает с обычными медиасерверами

Стриминг-сервер

KlugMedia поставляется с соответствующим серверным ПО, разработанным вместе с расширением и настроенным для приложений AIR: обработка потоков, надёжное переподключение, двусторонняя передача голоса, запись в MP4 и живой просмотр в веб-браузере.

Сервер описан на странице обзора: Стриминг-сервер.

Поддерживаемые платформы

iOS arm64
Android arm64 · armv7
macOS Apple silicon · Intel
Приложения iPad на Mac Apple silicon · macOS 26 и 27

Приложения iPad на Mac

На Mac с Apple silicon сборка iOS приложения AIR может работать как приложение iPad. KlugMedia поддерживает этот режим с камерой, живым видео и двусторонней голосовой связью, включая встроенную камеру FaceTime и внешние USB-камеры. Одна сборка подходит для iPhone, iPad и Mac.

Готово к iOS 27 и macOS 27

KlugMedia протестирован на iOS 27, iPadOS 27 и macOS 27, на iPhone, iPad, MacBook и Mac mini, а также на iOS 17. Главное в этом выпуске:

  • Усиленный путь приёма: остановка и перезапуск прямого потока безопасны в любой момент, в том числе при таймингах iOS 27
  • Стабильный предпросмотр камеры на macOS 27 для приложений iPad на Mac, пока камера запускается, останавливается или переключается
  • Правильная ориентация на любом Mac: встроенные и USB-камеры стоят ровно в предпросмотре и у получателя, на macOS 26 и 27
  • Быстрое переключение камеры на Mac между камерой FaceTime и USB-камерами, примерно за секунду
  • Чистый голос по Wi-Fi ноутбука: адаптивный буфер поглощает короткие всплески Wi-Fi, типичные для MacBook, и уменьшается обратно, когда сеть спокойна

Начало работы

Добавьте расширение в дескриптор вашего приложения:

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

Запросите разрешение на камеру и микрофон до первого запуска. После этого захват принадлежит расширению: не открывайте одновременно Camera или Microphone из AIR.

Примеры кода

Пять полных сценариев из API, который ежедневно работает в наших приложениях. Каждый вызов возвращается сразу; результаты приходят в виде StatusEvent. Полная документация →

1 · Публикация потока с камеры
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 · Приём и следование раскладке
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 · Двусторонний голос с эхоподавлением
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 );
}
Голосовые пакеты передаются как сообщения с данными по собственной паре потоков. Стриминг-сервер Klug ретранслирует их «из коробки»; другим серверам RTMP нужно пересылать NetStream.send подписчикам.
4 · Предпросмотр, переключение камеры, фонарик, зум, снимок
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 · Чистая остановка и перезапуск
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" );

Обзор API

isSupportedTrue там, где доступна нативная медиасессия.
startPublish(…)Запускает камеру и публикует H.264 по RTMP: размер, fps, битрейт, интервал ключевых кадров, камера, необязательный логин RTMP.
stopPublish()Останавливает публикацию; камера освобождается, если предпросмотр не показывается.
startReceive(…)Воспроизводит удалённый поток нативно внутри прямоугольника сцены: вписывание по пропорциям или обрезка по размеру с поворотом (растягивание на Android).
setReceiveFrame(x, y, w, h)Перемещает и меняет размер нативного видео — для поворота, складных телефонов и полноэкранного режима.
stopReceive()Останавливает воспроизведение и убирает нативное представление.
showPreview(…) / hidePreview()Нативный предпросмотр камеры поверх сцены — отдельно или рядом с живой публикацией.
switchCamera()Переключает на следующую камеру во время трансляции: фронтальная и задняя на iPhone и iPad, встроенная и USB-камеры на Mac.
setTorch(on) / hasTorchПодсветка камеры во время трансляции и наличие её на устройстве.
setCameraZoom(step)Реальный зум камеры на iOS и Android, 0..8 для 1.0x–2.0x; поток тоже масштабируется.
setVideoBitrate(kbps)Изменяет битрейт кодировщика в прямом эфире.
captureSnapshot(w, h)Сохраняет JPEG из живого изображения камеры.
isiOSAppOnMacTrue, когда сборка iOS работает как приложение iPad на Mac с Apple silicon.
OpusVoiceBridgeДвусторонний голос: запуск, остановка, эхоподавление, динамик, усиление, буфер воспроизведения.
Red5OpusTransportПередаёт пакеты Opus по вашему соединению RTMP на двух выделенных потоках.

События статуса

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

Купить KlugMedia

Годовая лицензия на одно приложение AIR со всеми обновлениями в течение 12 месяцев. После оплаты вы получаете расширение, библиотеку ActionScript и документацию по e-mail, обычно в течение одного рабочего дня. Лицензия и условия

Базовый
€99 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Без поддержки
Купить Базовый
Стандартный
€349 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 7 дней
Купить Стандартный
Приоритетный
€699 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 48 часов
Купить Приоритетный
Налоги рассчитываются при оформлении заказа через Link (Stripe). ID приложения вашего приложения AIR вы указываете при оформлении заказа.

Требования

AIR SDK51.x (HARMAN)
iOSiOS 17 или новее
AndroidAndroid 6.0 (API 23) или новее
macOSmacOS 11 или новее
Приложения iPad на MacApple silicon, macOS 26 или новее
РазрешенияКамера и микрофон
СерверЛюбой сервер RTMP; рекомендуется соответствующий стриминг-сервер Klug