live_media_stream_sdk 0.1.0
live_media_stream_sdk: ^0.1.0 copied to clipboard
Self-hosted Flutter live streaming with native Opus and VP8/VP9 encoding, WebM output, advanced camera/audio controls, and any binary WebSocket server.
live_media_stream_sdk #
English #
A Flutter SDK for building low-cost, self-hosted live audio and video applications without requiring a dedicated media server, RTMP service, or WebRTC SFU.
The SDK captures camera and microphone input, performs native Opus and VP8/VP9 encoding on the device, creates the packet metadata, and can produce a live WebM stream. Your backend can therefore be a regular binary-capable WebSocket server that accepts frames and forwards them to subscribers or stores them. The included transport handles framing, metadata, reconnect attempts, and keyframe resynchronization.
This makes the package suitable for private broadcasts, field reporting, education, internal company streams, intercom systems, event audio, remote observation, and applications that need to own their transport and infrastructure.
A specialized media server is not required for ingest. Your WebSocket backend and receiving clients must still implement authentication, room routing, access control, scaling, and playback/decoding appropriate to your application. The SDK does not provide a hosted relay service or viewer UI.
Features #
Server and transport #
- No RTMP server, WebRTC SFU, MCU, or hosted media SDK is required for ingest.
- Works with a standard binary WebSocket endpoint.
- Transport-independent API for SignalR, native sockets, message brokers, or application-specific transports.
- One binary frame contains protocol version, JSON metadata, and raw media; payloads are not inflated with base64.
- Room, sender, receiver, user, command, and custom header metadata.
- Automatic reconnect attempts and a fresh keyframe request after reconnect.
- Incoming JSON control messages and binary messages are exposed to the app.
- Transport is optional: consume packets directly and send or store them yourself.
Camera and video #
- Native camera capture and hardware-supported VP8/VP9 encoding.
- Front and rear camera selection and live camera switching.
- 480p, 720p, and 1080p profiles.
- Configurable frame rate and video bitrate.
- Runtime bitrate changes without restarting the stream.
- Manual keyframe requests for viewer synchronization and reconnect recovery.
- Audio-only, video-only, and combined audio/video operation.
- Per-packet timestamps, sequence numbers, dimensions, codec, rotation, camera position, bitrate, and keyframe metadata.
- iOS Flutter texture preview with correct aspect ratio and orientation.
- iOS thermal protection reduces FPS/bitrate under heat, temporarily pauses video at critical temperature, and restores it with a keyframe after cooling.
Microphone and audio #
- Native Opus encoding with configurable bitrate.
- Mono/stereo selection and 8, 12, 16, 24, or 48 kHz sample rates, subject to device support.
- Built-in, wired headset, Bluetooth, and USB input discovery and selection.
- Deterministic microphone priority helper for field devices.
- Android software input gain from
0.0to8.0with clipping protection. - Android device-dependent noise suppression, automatic gain control, and acoustic echo cancellation.
- iOS preferred-input routing and voice-chat audio session mode when echo cancellation is requested.
- Android voice activity detection with configurable silence threshold and hangover; silent frames can be skipped before encoding.
- Live dB, peak, silence, clipping, audio-focus, and device-change events.
Output, lifecycle, and diagnostics #
- Independent
AudioPacketandVideoPacketoutput. - Ordered live
WebmPacketoutput containing VP8/VP9 and Opus. WebmStreamRecorderhelper for writing an emitted WebM stream to a file.- Pause/resume and clean asynchronous shutdown with final muxer flushing.
- Android camera/microphone foreground service with customizable notification.
- iOS background audio; camera automatically stops in the background and resumes with a keyframe in the foreground.
- Live upload/encoding bitrate, FPS, CPU, memory, packet, dropped-frame, keyframe, audio-level, effect, and thermal statistics.
Platform matrix #
| Capability | Android | iOS |
|---|---|---|
| Opus audio and VP8/VP9 video | ✓ | ✓ |
| Audio-only, video-only, audio/video | ✓ | ✓ |
| Separate packet and live WebM output | ✓ | ✓ |
| Front/rear camera and runtime video controls | ✓ | ✓ |
| Microphone discovery and selection | ✓ | ✓ |
| Native Flutter texture preview | — | ✓ |
| Camera/microphone foreground service | ✓ | — |
| Background audio with camera recovery | — | ✓ |
| Thermal video protection | — | ✓ |
The iOS binary supports physical iOS devices and Apple Silicon simulators.
Intel (x86_64) iOS simulators are not supported by the bundled libvpx
binary. Camera capture is unavailable when the selected simulator has no
camera input.
Installation #
dependencies:
live_media_stream_sdk: ^0.1.0
Import the public API:
import 'package:live_media_stream_sdk/live_media_stream_sdk.dart';
The host application is responsible for requesting camera, microphone, and notification permissions before starting a stream.
Android #
The plugin manifest declares camera, microphone, foreground-service, and notification permissions. On Android 13 and later, request notification permission in the host app. Start a camera/microphone foreground service while the application is visible to satisfy Android's while-in-use restrictions.
iOS #
Add usage descriptions to the host application's Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for live video.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for live audio.</string>
To continue audio while the app is in the background, also add:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
iOS suspends camera capture in the background. The plugin keeps audio active and restarts video with a keyframe when the application returns to the foreground.
Quick start #
final controller = LiveMediaStreamController();
await controller.initialize();
final packetSubscription = controller.packets.listen((packet) {
// Store, forward, or inspect encoded media packets.
});
await controller.start(
const LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioVideo,
videoCodec: VideoCodec.vp8,
audioCodec: AudioCodec.opus,
resolution: StreamResolution.p480,
framesPerSecond: 20,
videoBitrate: 800000,
audioBitrate: 64000,
),
);
// Later:
await controller.stop();
await packetSubscription.cancel();
await controller.dispose();
For long iOS sessions, VP8 at 480p, 15–20 FPS, and 600–900 Kbit/s is a good starting profile. The plugin automatically reduces video work under serious thermal pressure and temporarily switches to audio-only at the critical thermal state.
Usage guide #
1. Request permissions #
Request the permissions required by the selected mode before calling
start():
audioOnly: microphonevideoOnly: cameraaudioVideo: camera and microphone- Android 13+: notifications when the foreground-service notification is used
Permission prompts belong to the host application. Use a permission package of your choice or your existing native permission flow.
2. Create and initialize the controller #
Keep one controller for the lifetime of the streaming screen:
late final LiveMediaStreamController controller;
Future<void> initializeStreaming() async {
controller = LiveMediaStreamController();
await controller.initialize();
}
3. Listen to output and diagnostics #
Subscribe before starting so the first packets and events are not missed:
final packetSubscription = controller.packets.listen((packet) {
// AudioPacket, VideoPacket, or WebmPacket.
});
final eventSubscription = controller.events.listen((event) {
// Camera, audio, connection, state, and error events.
});
final statisticsSubscription = controller.statistics.listen((statistics) {
debugPrint(
'upload=${statistics.uploadBitsPerSecond}, '
'cpu=${statistics.cpuUsage}, '
'thermal=${statistics.thermalState}',
);
});
4. Configure and start the stream #
final configuration = LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioVideo,
outputMode: StreamOutputMode.separateAudioVideo,
cameraPosition: CameraPosition.front,
resolution: StreamResolution.p480,
framesPerSecond: 20,
videoBitrate: 800000,
audioBitrate: 64000,
audioProcessing: const AudioProcessingConfiguration(
noiseSuppression: true,
automaticGainControl: true,
echoCancellation: true,
),
);
await controller.start(configuration);
Use separateAudioVideo when your server accepts independent audio and video
packets. Use webm when the receiver expects one playable WebM byte stream.
transport is optional. Without one, encoded output is still available from
controller.packets, allowing the application to store or send it itself.
5. Control an active stream #
await controller.switchCamera(CameraPosition.back);
await controller.setVideoBitrate(600000);
await controller.requestVideoKeyFrame();
await controller.pause();
await controller.resume();
Only call video controls while video is enabled. Await each operation before starting another state change.
6. Stop and clean up #
await controller.stop();
await packetSubscription.cancel();
await eventSubscription.cancel();
await statisticsSubscription.cancel();
await controller.dispose();
Always await stop() before closing your socket or leaving the streaming
screen. This allows buffered packets and final WebM bytes to be delivered.
WebSocket transport #
The SDK is transport-independent. Use WebSocketLiveMediaTransport or
implement LiveMediaTransport for SignalR, a native socket, or another
protocol:
final transport = WebSocketLiveMediaTransport(
uri: Uri.parse('wss://your-server.example/live'),
);
await controller.start(
LiveStreamConfiguration(
transport: transport,
socketMessageBuilder: (packet) => LiveSocketMessage.fromMediaPacket(
packet,
action: 'media',
command: 'publish',
groupName: 'room-42',
senderConnectionId: 'connection-id',
userId: 15,
userType: 'publisher',
),
),
);
The included transport sends JSON metadata and the raw binary payload in one binary frame, without base64 expansion.
Minimal WebSocket relay #
The server does not have to decode the media when its only job is to relay frames. For example, this minimal Node.js server broadcasts each incoming binary frame to the other connections:
npm install ws
import { WebSocketServer } from 'ws';
const server = new WebSocketServer({ port: 8080 });
server.on('connection', (sender) => {
sender.on('message', (data, isBinary) => {
for (const viewer of server.clients) {
if (viewer !== sender && viewer.readyState === 1) {
viewer.send(data, { binary: isBinary });
}
}
});
});
This is intentionally a minimal architecture example. Add TLS (wss://),
authentication, rooms, authorization, rate limits, backpressure, monitoring,
and horizontal fan-out before production use. Receiving applications can use
WebSocketLiveMediaTransport.decode() to recover metadata and payload.
WebM output #
await controller.start(
const LiveStreamConfiguration(
outputMode: StreamOutputMode.webm,
videoCodec: VideoCodec.vp8,
audioCodec: AudioCodec.opus,
),
);
In WebM mode, controller.packets emits ordered WebmPacket chunks. Concatenate
them without reordering. Always await controller.stop() so the final muxer
bytes are emitted before disconnecting the transport.
iOS camera preview #
final textureId = await controller.getVideoTextureId();
Widget preview = textureId == null
? const SizedBox.shrink()
: LiveMediaPreview(textureId: textureId);
Android encoding is supported, but the public Flutter texture preview is currently iOS-only.
Audio processing and statistics #
AudioProcessingConfiguration controls gain, input selection, channel mode,
sample rate, echo cancellation, noise suppression, automatic gain control,
voice activity detection, and silence thresholds. See
AUDIO_FEATURES.md for platform-specific details.
Listen to controller.events and controller.statistics for audio levels,
stream state, encoded/upload bitrates, CPU use, active audio effects, and iOS
thermal state.
Example #
The example application provides a complete configuration and diagnostics
screen. Replace its placeholder WebSocket address with your server endpoint
before testing transport delivery.
License #
This package is available under the MIT License. The bundled iOS libvpx binary
has separate terms documented in
THIRD_PARTY_NOTICES.md.
Türkçe #
Özel bir media server, RTMP servisi veya WebRTC SFU kurmak zorunda kalmadan düşük maliyetli ve tamamen size ait canlı ses/video uygulamaları geliştirmenizi sağlayan bir Flutter SDK'sıdır.
SDK kamera ve mikrofon verisini cihazda yakalar; Opus ses ile VP8/VP9 video kodlamasını native olarak yapar, paket metadata'sını hazırlar ve istenirse canlı WebM akışı üretir. Böylece backend tarafında binary frame kabul eden normal bir WebSocket sunucusu kurmanız yeterlidir. Bu sunucu gelen frame'leri odadaki izleyicilere iletebilir veya kaydedebilir. Hazır WebSocket taşıyıcısı frame formatını, metadata'yı, yeniden bağlanma denemelerini ve bağlantı sonrası keyframe senkronizasyonunu yönetir.
Özel yayınlar, saha haberciliği, eğitim, şirket içi yayınlar, interkom sistemleri, etkinlik sesi, uzaktan gözlem ve kendi altyapısına sahip olmak isteyen uygulamalar için uygundur.
Yayın verisini almak için özel bir media server gerekmez. Ancak WebSocket sunucunuz ve izleyici uygulamalarınız; kimlik doğrulama, oda yönlendirme, erişim kontrolü, ölçekleme ve oynatma/decode işlemlerini kendi ihtiyacınıza göre gerçekleştirmelidir. SDK hazır bir bulut relay servisi veya izleyici arayüzü sunmaz.
Özellikler #
Sunucu ve taşıma katmanı
- Yayın verisini almak için RTMP server, WebRTC SFU/MCU veya ücretli bir medya SDK'sı gerekmez.
- Standart, binary mesaj destekleyen herhangi bir WebSocket endpoint'iyle çalışır.
- SignalR, native socket, mesaj kuyruğu veya özel protokoller için transport-bağımsız API sunar.
- Her binary frame; protokol sürümü, JSON metadata ve ham medya payload'ını içerir. Base64 kullanılmadığı için veri gereksiz büyümez.
- Oda/grup, gönderen, alıcı, kullanıcı, komut ve uygulamaya özel header metadata'sı taşınabilir.
- Bağlantı koptuğunda otomatik yeniden bağlanma denenir; bağlantı geldiğinde izleyicileri tekrar senkronlamak için yeni keyframe istenir.
- Sunucudan gelen JSON kontrol mesajları ve binary mesajlar uygulamaya aktarılır.
- Hazır transport'u kullanmak zorunlu değildir; paketleri doğrudan dinleyip kendi bağlantınızla gönderebilir veya kaydedebilirsiniz.
Kamera ve video
- Native kamera yakalama ve cihazın desteklediği donanım hızlandırmalı VP8/VP9 kodlama.
- Ön/arka kamera seçimi ve yayın sırasında kamera değiştirme.
- 480p, 720p ve 1080p çözünürlük profilleri.
- Ayarlanabilir FPS ve video bitrate.
- Yayını kapatmadan çalışma anında bitrate değiştirme.
- İzleyici senkronizasyonu ve yeniden bağlantı için elle keyframe isteme.
- Yalnızca ses, yalnızca video veya birlikte ses/video yayını.
- Her video paketinde sıra numarası, timestamp, çözünürlük, codec, dönüş açısı, kamera yönü, bitrate ve keyframe bilgisi.
- iOS'ta doğru en-boy oranı ve yönlendirmeyle Flutter texture kamera önizlemesi.
- iOS termal koruma: cihaz ısındığında FPS/bitrate düşürme, kritik sıcaklıkta videoyu geçici durdurma ve soğuyunca keyframe ile otomatik devam etme.
Mikrofon ve ses
- Native Opus kodlama ve ayarlanabilir ses bitrate.
- Cihaz desteğine bağlı mono/stereo ile 8, 12, 16, 24 veya 48 kHz örnekleme.
- Dahili mikrofon, kablolu kulaklık, Bluetooth ve USB girişlerini listeleme ve seçme.
- Saha cihazları için USB → kablolu → Bluetooth → dahili mikrofon şeklinde değiştirilebilir öncelikli seçim yardımcısı.
- Android'de
0.0–8.0aralığında yazılımsal gain ve clipping koruması. - Android'de cihaz desteğine bağlı gürültü azaltma, otomatik kazanç ve akustik yankı giderme.
- iOS'ta tercih edilen giriş cihazına yönlendirme ve yankı giderme istendiğinde voice-chat ses oturumu.
- Android'de ayarlanabilir sessizlik eşiği ve hangover süresiyle VAD; sessiz frame'ler kodlama öncesinde atlanabilir.
- Canlı dB, peak, sessizlik, clipping, audio focus ve cihaz değişikliği olayları.
Çıktı, yaşam döngüsü ve ölçümler
- Bağımsız
AudioPacketveVideoPacketçıkışı. - VP8/VP9 ve Opus içeren sıralı canlı
WebmPacketçıkışı. - WebM akışını dosyaya yazmak için
WebmStreamRecorder. - Duraklatma/devam ettirme ve muxer'ın son verilerini gönderen güvenli kapatma.
- Android'de metni değiştirilebilir kamera/mikrofon foreground service bildirimi.
- iOS'ta arka planda ses; kamera arka planda durur ve öne dönünce keyframe ile otomatik açılır.
- Upload/kodlama bitrate, FPS, CPU, bellek, paket, düşen frame, keyframe, ses seviyesi, etkin ses efektleri ve termal durum istatistikleri.
Platform karşılaştırması
| Özellik | Android | iOS |
|---|---|---|
| Opus ses ve VP8/VP9 video | ✓ | ✓ |
| Yalnızca ses, yalnızca video, ses/video | ✓ | ✓ |
| Ayrı paket ve canlı WebM çıkışı | ✓ | ✓ |
| Ön/arka kamera ve çalışma anında video kontrolü | ✓ | ✓ |
| Mikrofon listeleme ve seçme | ✓ | ✓ |
| Native Flutter texture önizlemesi | — | ✓ |
| Kamera/mikrofon foreground service | ✓ | — |
| Arka plan sesi ve kamera geri yükleme | — | ✓ |
| Termal video koruması | — | ✓ |
iOS ikilisi fiziksel iOS cihazları ve Apple Silicon simülatörleri destekler.
Paketteki libvpx ikilisi Intel (x86_64) iOS simülatörlerini desteklemez.
Seçilen simülatörde kamera girişi yoksa kamera yayını kullanılamaz.
Kurulum #
pubspec.yaml dosyanıza paketi ekleyin:
dependencies:
live_media_stream_sdk: ^0.1.0
Ardından genel API'yi içe aktarın:
import 'package:live_media_stream_sdk/live_media_stream_sdk.dart';
Yayın başlatılmadan önce kamera, mikrofon ve gerekiyorsa bildirim izinlerini istemek host uygulamanın sorumluluğundadır.
Android izinleri
Eklenti manifest dosyası kamera, mikrofon, foreground service ve bildirim izinlerini tanımlar. Android 13 ve sonrasında bildirim iznini uygulamanızdan istemelisiniz. Android'in kullanım-anı kısıtlamaları nedeniyle kamera veya mikrofon kullanan foreground service, uygulama görünür durumdayken başlatılmalıdır.
iOS izinleri
Host uygulamanın Info.plist dosyasına kullanım açıklamalarını ekleyin:
<key>NSCameraUsageDescription</key>
<string>Canlı video için kamera erişimi gereklidir.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Canlı ses için mikrofon erişimi gereklidir.</string>
Uygulama arka plandayken ses yayınını sürdürmek için ayrıca şunu ekleyin:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
iOS arka planda kamera yakalamayı durdurur. Eklenti ses yayınını sürdürür; uygulama tekrar öne geldiğinde kamerayı yeniden başlatır ve ilk video karesini keyframe olarak üretir.
Hızlı başlangıç #
Yukarıdaki Quick start örneği doğrudan kullanılabilir. Temel akış şöyledir:
LiveMediaStreamControlleroluşturun veinitialize()çağrısını bekleyin.- Üretilen veriler için
packets, olaylar içinevents, ölçümler içinstatisticsakışını dinleyin. - Bir
LiveStreamConfigurationilestart()çağrısını yapın. - Yayını bitirirken sırasıyla
stop()vedispose()çağrılarını mutlakaawaitedin.
Uzun iOS yayınları için VP8, 480p, 15–20 FPS ve 600–900 Kbit/s iyi bir başlangıç profilidir. Cihaz ciddi ölçüde ısındığında eklenti video yükünü otomatik azaltır. Termal durum kritik seviyeye ulaşırsa geçici olarak yalnızca ses yayınına geçer; cihaz soğuduğunda kamerayı yeniden başlatır.
Ayrıntılı kullanım #
1. Gerekli izinleri alın
start() çağrısından önce seçilen yayın modunun izinlerini kullanıcıdan alın:
audioOnly: mikrofonvideoOnly: kameraaudioVideo: kamera ve mikrofon- Android 13 ve sonrası: foreground service bildirimi kullanılacaksa bildirim
İzin isteme ekranları SDK tarafından açılmaz; bu işlem host uygulamaya aittir. Tercih ettiğiniz bir Flutter izin paketini veya mevcut native izin akışınızı kullanabilirsiniz.
2. Controller'ı oluşturun
Yayın ekranı boyunca aynı controller nesnesini saklayın:
late final LiveMediaStreamController controller;
Future<void> yayiniHazirla() async {
controller = LiveMediaStreamController();
await controller.initialize();
}
3. Paketleri, olayları ve istatistikleri dinleyin
İlk verileri kaçırmamak için yayın başlamadan önce stream'lere abone olun:
final paketAboneligi = controller.packets.listen((packet) {
// AudioPacket, VideoPacket veya WebmPacket gelir.
});
final olayAboneligi = controller.events.listen((event) {
// Kamera, ses, bağlantı, durum ve hata olayları gelir.
});
final istatistikAboneligi = controller.statistics.listen((statistics) {
debugPrint(
'upload=${statistics.uploadBitsPerSecond}, '
'cpu=${statistics.cpuUsage}, '
'termal=${statistics.thermalState}',
);
});
4. Yayını yapılandırıp başlatın
final ayarlar = LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioVideo,
outputMode: StreamOutputMode.separateAudioVideo,
cameraPosition: CameraPosition.front,
resolution: StreamResolution.p480,
framesPerSecond: 20,
videoBitrate: 800000,
audioBitrate: 64000,
audioProcessing: const AudioProcessingConfiguration(
noiseSuppression: true,
automaticGainControl: true,
echoCancellation: true,
),
);
await controller.start(ayarlar);
Sunucunuz ses ve video paketlerini ayrı kabul ediyorsa separateAudioVideo,
oynatılabilir tek bir byte akışı bekliyorsa webm çıkışını seçin.
transport vermek zorunlu değildir. Transport verilmezse kodlanmış veriler
yine controller.packets üzerinden gelir; uygulama bu verileri kendisi
kaydedebilir veya kendi bağlantısıyla gönderebilir.
5. Aktif yayını kontrol edin
await controller.switchCamera(CameraPosition.back);
await controller.setVideoBitrate(600000);
await controller.requestVideoKeyFrame();
await controller.pause();
await controller.resume();
Video komutlarını yalnızca video açıkken çağırın. Bir durum değiştirme işlemi
bitmeden diğerini başlatmamak için tüm çağrıları await edin.
6. Yayını güvenli biçimde kapatın
await controller.stop();
await paketAboneligi.cancel();
await olayAboneligi.cancel();
await istatistikAboneligi.cancel();
await controller.dispose();
Socket bağlantısını kapatmadan veya yayın ekranından çıkmadan önce stop()
çağrısını mutlaka await edin. Böylece bekleyen paketler ve WebM akışının son
baytları kaybolmaz.
Gelişmiş kullanım örnekleri #
Harici mikrofonu otomatik seçerek kaliteli ses yayını
Bağlı mikrofonları listeleyip USB, kablolu kulaklık, Bluetooth ve dahili mikrofon sırasıyla en uygun girişi seçebilirsiniz:
final mikrofonlar = await controller.getAudioInputDevices();
final mikrofon = AudioInputDeviceSelector.select(mikrofonlar);
await controller.start(
LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioOnly,
audioCodec: AudioCodec.opus,
audioBitrate: 64000,
audioProcessing: AudioProcessingConfiguration(
inputDevice: mikrofon,
channelMode: AudioChannelMode.mono,
sampleRate: 48000,
gain: 1.25,
noiseSuppression: true,
automaticGainControl: true,
echoCancellation: true,
voiceActivityDetection: true,
silenceThresholdDb: -50,
vadHangoverMilliseconds: 250,
),
),
);
Android'de VAD açıkken eşik altında kalan sessiz frame'ler kodlanmayarak bant
genişliği ve işlemci kullanımı azaltılabilir. Native ses efektlerinin gerçekten
etkin olup olmadığını LiveStreamStatistics içindeki
noiseSuppressorEnabled, automaticGainControlEnabled ve
echoCancelerEnabled alanlarından kontrol edin; destek cihazdan cihaza değişir.
Isınmayı gözeten kamera profili
Uzun süreli yayınlar için 480p ve 20 FPS ile başlayıp ağ veya cihaz durumuna göre bitrate'i yayın sırasında değiştirebilirsiniz:
await controller.start(
const LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioVideo,
videoCodec: VideoCodec.vp8,
resolution: StreamResolution.p480,
cameraPosition: CameraPosition.back,
framesPerSecond: 20,
videoBitrate: 800000,
audioBitrate: 64000,
qualityMode: QualityMode.automatic,
),
);
// Ağ zayıfladığında yayını kesmeden düşürün.
await controller.setVideoBitrate(550000);
// Kamerayı değiştirip izleyicilere yeni bir tam kare gönderin.
await controller.switchCamera(CameraPosition.front);
await controller.requestVideoKeyFrame();
iOS'ta termal koruma ayrıca otomatik çalışır. Güncel durumu
statistics.thermalState ve statistics.thermalLimited alanlarından
izleyebilirsiniz.
WebM yayınını aynı anda gönderme ve kaydetme
import 'dart:io';
final kaydedici = WebmStreamRecorder(
File('/uygulamanin-yazabildigi-klasor/yayin.webm'),
);
await kaydedici.start(controller.packets);
await controller.start(
LiveStreamConfiguration(
mediaMode: StreamMediaMode.audioVideo,
outputMode: StreamOutputMode.webm,
transport: WebSocketLiveMediaTransport(
uri: Uri.parse('wss://sunucunuz.example/live'),
),
),
);
// Yayın biterken sıra önemlidir.
await controller.stop();
final dosya = await kaydedici.stop();
await controller.dispose();
Dosya yolunu path_provider gibi bir paketle uygulamanın yazma izni olan
klasöründen üretin.
WebSocket ve özel taşıma katmanı #
SDK herhangi bir sunucu protokolüne bağımlı değildir.
WebSocketLiveMediaTransport kullanabilir veya SignalR, native WebSocket ya
da kendi protokolünüz için LiveMediaTransport arayüzünü uygulayabilirsiniz.
Yukarıdaki WebSocket transport örneğinde bağlantı ve
mesaj metadata'sı gösterilmiştir.
Pakete dahil WebSocket taşıyıcısı, JSON metadata ile ham binary medya verisini tek bir binary frame içinde gönderir. Base64 kullanılmadığı için medya verisi gereksiz yere büyümez.
Basit WebSocket sunucusu nasıl olur?
Sunucu yalnızca yayın verisini diğer bağlantılara aktaracaksa codec çözmesine veya mux işlemi yapmasına gerek yoktur. Yukarıdaki Minimal WebSocket relay örneği, gelen binary frame'leri diğer istemcilere olduğu gibi ileten çok küçük bir Node.js sunucusu gösterir.
Bu örnek yalnızca mimariyi anlatır. Gerçek kullanımda wss://, kimlik
doğrulama, odalar, yetkilendirme, hız sınırı, yavaş istemci kontrolü, izleme ve
yatay ölçekleme eklenmelidir. Alıcı Flutter uygulaması
WebSocketLiveMediaTransport.decode() ile metadata ve ham payload'ı ayırabilir.
WebM çıkışı #
outputMode: StreamOutputMode.webm seçildiğinde controller.packets, sıralı
WebmPacket parçaları üretir. Bu parçaları sıralarını değiştirmeden
birleştirin. Muxer'ın son baytları bağlantı kapanmadan gönderilebilsin diye
yayını durdururken her zaman await controller.stop() kullanın.
iOS kamera önizlemesi #
Yayın başlatıldıktan sonra controller.getVideoTextureId() ile texture
kimliğini alın ve LiveMediaPreview(textureId: textureId) bileşenine verin.
Video kodlama Android'de de desteklenir; ancak Flutter texture tabanlı genel
önizleme API'si şu anda yalnızca iOS'ta kullanılabilir.
Ses işleme ve istatistikler #
AudioProcessingConfiguration üzerinden gain, giriş cihazı, kanal modu,
örnekleme hızı, yankı giderme, gürültü azaltma, otomatik kazanç, ses etkinliği
algılama ve sessizlik eşiği ayarlanabilir. Platform ayrıntıları için
AUDIO_FEATURES.md dosyasına bakın.
controller.events ve controller.statistics; ses seviyesi, yayın durumu,
kodlama/yükleme bitrate değerleri, CPU kullanımı, etkin ses efektleri ve iOS
termal durumu gibi bilgileri sağlar.
Örnek uygulama #
example klasöründeki uygulama kapsamlı bir ayar ve tanılama ekranı içerir.
Taşıma katmanını test etmeden önce örnek WebSocket adresini kendi sunucu
adresinizle değiştirin.
Lisans #
Paket MIT Lisansı ile sunulur. iOS paketine dahil edilen libvpx ikilisinin
ayrı koşulları THIRD_PARTY_NOTICES.md dosyasında
belirtilmiştir.