本文詳細說明Flutter框架直播推流SDK基本使用流程,以及相關功能的使用示例。
Flutter框架直播推流SDK特性
支持RTMP推流協議。
支持基于UDP的ARTC協議推流。
使用視頻H.264編碼以及音頻AAC編碼。
支持碼控、分辨率、顯示模式等自定義配置。
支持多種攝像頭相關操作。
支持實時美顏和自定義美顏效果調節。
支持增、刪動態貼紙實現動態水印效果。
支持自定義YUV、PCM等外部音視頻輸入。
支持純音視頻推流以及后臺推流。
支持背景音樂及其相關操作。
支持視頻截圖功能。
支持自動重連、異常處理。
支持音頻3A算法。
增加視頻軟編、硬編切換邏輯,提升編碼模塊穩定性。
功能限制
Flutter框架直播推流SDK需注意以下限制:
您只能在推流之前設置橫豎屏模式,不支持在直播的過程中實時切換。
在推流設定為橫屏模式時,需設定界面為不允許自動旋轉。
在硬編模式下,考慮編碼器兼容問題分辨率會使用16的倍數,如設定為540P,則輸出的分辨率為544*960,在設置播放器視圖大小時需按輸出分辨率等比縮放,避免黑邊等問題。
使用流程
基本使用流程如下:
步驟 | 描述 |
一、注冊SDK | 配置License相關參數,注冊直播推流SDK。若不調用注冊函數,推流功能無法使用。 |
二、配置推流參數 | 完成推流基本配置、碼率控制配置、分辨率自適應配置等。 |
三、進行推流 | 初始化SDK、注冊推流回調、創建預覽視圖后可以開始推流。用戶可以根據業務需求添加推流控制、設置背景音樂、攝像頭、外部音頻、動態貼紙等。 說明 阿里云視頻直播不允許同一時間向同一個推流URL進行多路推流(第二路推流會被拒絕)。 |
注冊SDK
Flutter框架直播推流SDK已接入一體化License服務,申請并配置License請參見直播推流SDK License集成指南。
在使用推流功能前必須進行注冊,否則無法使用直播推流SDK功能。
創建AlivcBase實例。
/// 引入頭文件 import 'package:flutter_livepush_plugin/live_base.dart'; AlivcBase alivcBase = AlivcBase.init();
注冊SDK。
重要在調用注冊SDK方法前,需要提前配置License。
alivcBase.registerSDK();
設置監聽回調接口。
alivcBase.setObserver();
SDK Licence校驗接口回調。
alivcBase.setOnLicenceCheck((result, reason) { if (result == AlivcLiveLicenseCheckResultCode.success) { // 注冊SDK成功 } });
使用AlivcBase其它接口。
/// 獲取原生直播推流SDK版本號 String sdkVersion = await AlivcBase.getSdkVersion(); /// 啟用控制臺日志打印 AlivcBase.setConsoleEnable(true); /// 設置log級別為Debug調試級別 AlivcBase.setLogLevel(AlivcLivePushLogLevel.debug); /// 設置Log路徑 String logPath = "xxxx"; // xxxx為手機存放的路徑 int maxPartFileSizeInKB = 100 * 1024 * 1024; // 自定義設置 AlivcBase.setLogPath(logPath, maxPartFileSizeInKB);
配置推流參數
創建AlivcLivePusher實例。
/// 引入頭文件 import 'package:flutter_livepush_plugin/live_pusher.dart'; import 'package:flutter_livepush_plugin/live_push_config.dart'; AlivcLivePusher livePusher = AlivcLivePusher.init();
創建Config,將AlivcLivePusherConfig同AlivcLivePusher聯系起來。
livePusher.createConfig();
創建AlivcLivePusherConfig實例。
AlivcLivePusherConfig pusherConfig = AlivcLivePusherConfig.init();
設置推流參數根據使用場景,自定義設置。
基本推流配置對應參數都有默認值,建議采用默認值,即您可以進行簡單初始化,不做配置。 示例代碼如下:
/// 設置分辨率為540P pusherConfig.setResolution(AlivcLivePushResolution.resolution_540P); /// 設置視頻采集幀率為20fps。建議用戶使用20fps pusherConfig.setFps(AlivcLivePushFPS.fps_20); /// 打開碼率自適應,默認為true pusherConfig.setEnableAutoBitrate(true); /// 設置關鍵幀間隔。關鍵幀間隔越大,延時越高。建議設置為1-2 pusherConfig.setVideoEncodeGop(AlivcLivePushVideoEncodeGOP.gop_2); /// 設置重連時長為2s。單位為毫秒,設置不小于1秒,建議使用默認值即可。 pusherConfig.setConnectRetryInterval(2000); /// 設置預覽鏡像為關閉 pusherConfig.setPreviewMirror(false); /// 設置推流方向為豎屏 pusherConfig.setOrientation(AlivcLivePushOrientation.portrait);
配置碼率控制。
碼率控制通過AlivcLivePushQualityMode枚舉參數配置。直播推流SDK提供以下碼率控制模式,請根據實際需求修改參數值。
碼率控制模式
描述
示例代碼
AlivcLivePushQualityMode.resolution_first
清晰度優先模式。SDK內部會對碼率參數進行配置,優先保障推流視頻的清晰度。
pusherConfig.setQualityMode(AlivcLivePushQualityMode.resolution_first);
AlivcLivePushQualityMode.fluency_first
流暢度優先模式。SDK內部會對碼率參數進行配置,優先保障推流視頻的流暢度。
pusherConfig.setQualityMode(AlivcLivePushQualityMode.fluency_first);
AlivcLivePushQualityMode.custom
自定義模式。SDK會根據開發者設置的碼率進行配置。設置為自定義模式時,您可以選擇配置畫質優先或者流暢度優先,并自行設定初始碼率、最小碼率和目標碼率。
初始碼率:開始直播時的碼率。
最小碼率:當網絡較差時,碼率會逐步減低到最小碼率,以減少視頻的卡頓。
目標碼率:當網絡較好時,碼率會逐步提高到目標碼率,以提高視頻清晰度。
pusherConfig.setQualityMode(AlivcLivePushQualityMode.custom);
說明選擇清晰度優先或流暢度優先模式時,不需設置初始碼率、最小碼率和目標碼率(setInitialVideoBitrate、setMinVideoBitrate、setTargetVideoBitrate)。直播推流SDK內部策略會自動保障在網絡抖動情況下優先考慮視頻清晰度或流暢度。
選擇自定義碼率時,請參考阿里云推薦設置配置對應碼率。推薦設置請參考下表內容。
自定義碼率控制推薦設置(畫質優先)
分辨率
初始碼率 initialVideoBitrate
最小碼率 minVideoBitrate
目標碼率 targetVideoBitrate
360P
600
300
1000
480P
800
300
1200
540P
1000
600
1400
720P
1500
600
2000
1080P
1800
1200
2500
自定義碼率控制推薦設置(流暢度優先)
分辨率
初始碼率 initialVideoBitrate
最小碼率 minVideoBitrate
目標碼率 targetVideoBitrate
360P
400
200
600
480P
600
300
800
540P
800
300
1000
720P
1000
300
1200
1080P
1500
1200
2200
配置分辨率自適應。
分辨率自適應即動態調整推流分辨率。開啟功能后,當網絡較差時會自動降低分辨率以提高視頻的流暢度和清晰度。示例代碼如下:
/// 設置打開分辨率自適應 pusherConfig.setEnableAutoResolution(true);
重要某些播放器可能不支持動態分辨率,如果您需要使用分辨率自適應功能,建議使用阿里云播放器。
分辨率自適應只有在清晰度優先或流暢度優先時才會生效(AlivcLivePushQualityMode枚舉參數配置),自定義模式時無效。
配置圖片推流。
為了更好的用戶體驗,直播推流SDK提供了后臺圖片推流和碼率過低時進行圖片推流的設置。當SDK退至后臺時默認暫停推流視頻,只推流音頻,此時可以設置圖片來進行圖片推流和音頻推流。示例代碼如下:
/// 設置暫停圖片 String pauseImagePath = "xxxx"; // xxxx為手機存放的圖片路徑 pusherConfig.setPauseImg(pauseImagePath);
另外,當網絡較差時您可以根據自己的需求設置推流一張靜態圖片。設置圖片后,SDK檢測到當前碼率較低時,會推流此圖片,避免視頻流卡頓。示例代碼如下所示:
/// 設置網絡差圖片 String networkPoorImagePath = "xxxx"; // xxxx為手機存放的圖片路徑 pusherConfig.setNetworkPoorImg(networkPoorImagePath);
配置預覽顯示模式。
直播推流SDK支持三種預覽模式,預覽顯示模式不影響推流。
AlivcPusherPreviewDisplayMode.preview_scale_fill:預覽顯示時,鋪滿窗口。當視頻比例和窗口比例不一致時,預覽會有變形。
AlivcPusherPreviewDisplayMode.preview_aspect_fit:預覽顯示時,保持視頻比例。當視頻比例與窗口比例不一致時,預覽會有黑邊。
AlivcPusherPreviewDisplayMode.preview_aspect_fill:預覽顯示時,剪切視頻以適配窗口比例。當視頻比例和窗口比例不一致時,預覽會裁剪視頻。
示例代碼如下:
/// 設置預覽顯示模式為保持視頻比例 pusherConfig.setPreviewDisplayMode(AlivcPusherPreviewDisplayMode.preview_aspect_fit);
iOS系統下重置config。
iOS系統下不再使用[AlivcLivePusherConfig時,建議主動調用下該方法,重置原生config對象,下次再創建時恢復為默認狀態。
建議在AlivcLivePusher已經調用destroy的情況下調用該方法。
/// iOS系統下重置config livePusher.destroyConfigForIOS();
進行推流
創建推流引擎實例。
livePusher.initLivePusher();
注冊推流監聽回調。
/// 設置推流狀態監聽回調 livePusher.setInfoDelegate(); /// 設置推流錯誤監聽回調 livePusher.setErrorDelegate(); /// 設置推流網絡監聽回調 livePusher.setNetworkDelegate();
監聽推流相關回調。
/// 推流錯誤監聽回調 /// 系統錯誤回調 livePusher.setOnSDKError((errorCode, errorDescription) {}); /// 系統錯誤回調 livePusher.setOnSystemError((errorCode, errorDescription) {}); /// 推流狀態監聽回調 /// 開始預覽回調 livePusher.setOnPreviewStarted(() {}); /// 停止預覽回調 livePusher.setOnPreviewStoped(() {}); /// 渲染第一幀回調 livePusher.setOnFirstFramePreviewed(() {}); /// 推流開始回調 livePusher.setOnPushStarted(() {}); /// 攝像頭推流暫停回調 livePusher.setOnPushPaused(() {}); /// 攝像頭推流恢復回調 livePusher.setOnPushResumed(() {}); /// 重新推流回調 livePusher.setOnPushRestart(() {}); /// 推流停止回調 livePusher.setOnPushStoped(() {}); /// 推流網絡監聽回調 /// 推流鏈接失敗 livePusher.setOnConnectFail((errorCode, errorDescription) {}); /// 網絡恢復 livePusher.setOnConnectRecovery(() {}); /// 連接被斷開 livePusher.setOnConnectionLost(() {}); /// 網絡差回調 livePusher.setOnNetworkPoor(() {}); /// 重連失敗回調 livePusher.setOnReconnectError((errorCode, errorDescription) {}); /// 重連開始回調 livePusher.setOnReconnectStart(() {}); /// 重連成功回調 livePusher.setOnReconnectSuccess(() {});
創建推流預覽視圖。
var x = 0.0; // 自定義數值 var y = 0.0; // 自定義數值 var width = MediaQuery.of(context).size.width; // 自定義數值 var height = MediaQuery.of(context).size.height; // 自定義數值 AlivcPusherPreview pusherPreviewView = AlivcPusherPreview( onCreated: _onPusherPreviewCreated, x: x, y: y, width: width, height: height); return Container( color: Colors.black, width: width, height: height, child: pusherPreviewView);
開始預覽。
/// 視圖創建回調 _onPusherPreviewCreated(id) { /// 開始預覽 livePusher.startPreview(); }
說明如果flutter工程設置的屏幕方向是豎屏,在設置推流方向setOrientation為橫屏時,此時手動調用旋屏方法創建推流預覽視圖的時候,在視圖創建回調調用開始預覽startPreview方法之后,如果出現預覽渲染畫面沒有鋪滿設置的預覽視圖大小,則建議在調用開始預覽方法之前手動執行下延遲一段時間再調用,比如延遲100ms:
Future.delayed(Duration(milliseconds: 100));
開始推流。預覽成功后才可以開始推流。
String pushURL = "推流測試地址(rtmp://......)"; livePusher.startPushWithURL(pushURL);
設置其他推流控制。
/// 暫停攝像頭推流。可以調用[setPauseImg]后調用[pause]接口,從攝像頭推流切換成靜態圖片推流,音頻推流繼續。 livePusher.pause(); /// 從靜態圖片推流切換成攝像頭推流,音頻推流繼續 livePusher.resume(); /// 推流狀態下可調用停止推流,完成后推流停止 livePusher.stopPush(); /// 在預覽狀態下才可以調用停止預覽,正在推流狀態下,調用停止預覽無效。預覽停止后,預覽畫面定格在最后一幀 livePusher.stopPreview(); /// 推流狀態下或者接收到所有Error相關回調狀態下可調用重新推流,且Error狀態下只可以調用此接口(或者[reconnectPushAsync]重連)或者調用[destory]銷毀推流。完成后重新開始推流,重啟[AlivcLivePusher]內部的一切資源,包括預覽、推流等等restart livePusher.restartPush(); /// 推流狀態下或者接收到[setNetworkDelegate]相關的Error回調狀態下可調用此接口, 且Error狀態下只可以調用此接口(或者[restartPush]重新推流)或者調用[destory]銷毀推流。完成后推流重連,重新鏈接推流 livePusher.reconnectPushAsync(); /// 銷毀推流后,推流停止,預覽停止,預覽畫面移除。[AlivcLivePusher]相關的一切資源銷毀 livePusher.destory();
設置背景音樂。
/// 開始播放背景音樂 String musicPath = "xxxx"; // xxxx為手機存放的音樂資源路徑 livePusher.startBGMWithMusicPathAsync(musicPath); /// 停止播放背景音樂。若當前正在播放BGM,并且需要切換歌曲,只需要調用開始播放背景音樂接口即可,無需停止當前正在播放的背景音樂 livePusher.stopBGMAsync(); /// 暫停播放背景音樂,背景音樂開始播放后才可調用此接口 livePusher.pauseBGM(); /// 恢復播放背景音樂,背景音樂暫停狀態下才可調用此接口 livePusher.resumeBGM(); /// 開啟循環播放音樂 livePusher.setBGMLoop(true); /// 設置降噪開關。打開降噪后,將對采集到的聲音中非人聲的部分進行過濾處理。可能存在對人聲稍微抑制作用,建議讓用戶自由選擇是否開啟降噪功能,默認不使用 livePusher.setAudioDenoise(true); /// 設置耳返開關。耳返功能主要應用于KTV場景。打開耳返后,插入耳機將在耳機中聽到主播說話聲音。關閉后,插入耳機無法聽到人聲。未插入耳機的情況下,耳返不起作用 livePusher.setBGMEarsBack(true); /// 混音設置,設置背景音樂音量 livePusher.setBGMVolume(50); // 設置數值范圍:[0 ~ 100],默認:50 /// 混音設置,設置人聲采集音量 livePusher.setCaptureVolume(50); // 設置數值范圍:[0 ~ 100] 默認:50 /// 設置靜音。靜音后音樂聲音和人聲輸入都會靜音。要單獨設置音樂或人聲靜音可以通過混音音量設置接口來調整 livePusher.setMute(true);
監聽背景音樂相關回調。
/// 背景音樂播放完畢 livePusher.setOnBGMCompleted(() {}); /// 背景音樂下載播放超時 livePusher.setOnBGMDownloadTimeout(() {}); /// 背景音樂開啟失敗 livePusher.setOnBGMOpenFailed(() {}); /// 背景音樂暫停播放 livePusher.setOnBGMPaused(() {}); /// 背景音樂當前播放進度 livePusher.setOnBGMProgress((progress, duration) {}); /// 背景音樂恢復播放 livePusher.setOnBGMResumed(() {}); /// 背景音樂開始播放 livePusher.setOnBGMStarted(() {}); /// 背景音樂停止播放 livePusher.setOnBGMStoped(() {});
設置推流截圖。
/// 調用截圖 String dir = "xxxx"; // xxxx代表設置路徑 if (Platform.isIOS) { /// dir設置要求:iOS系統下是指定存放相對的路徑,會在系統沙盒路徑下自動生成自定義的目錄,設置為""時,則保存在系統沙盒路徑下。 /// dirTypeForIOS:可選設置。不設置默認是放在系統沙盒的[document]路徑下。 livePusher.snapshot(1, 0, dir, dirTypeForIOS: AlivcLiveSnapshotDirType.document); } else { livePusher.snapshot(1, 0, dir); } /// 設置截圖回調,需要在調用[snapshot]后調用 livePusher.setSnapshotDelegate(); /// 監聽截圖回調 livePusher.setOnSnapshot((saveResult, savePath, {dirTypeForIOS}) { // 截圖保存成功 if (saveResult == true) { if (Platform.isIOS) { // 根據dirTypeForIOS + savePath拼接獲取沙盒路徑下的完整截圖保存路徑 } else { // 根據savePath獲取SD下的截圖保存路徑 } } });
攝像頭相關操作。
/// 切換前后攝像頭 livePusher.switchCamera(); /// 開啟/關閉閃光燈,在前置攝像頭時開啟閃關燈無效 livePusher.setFlash(false); /// 焦距調整,即可實現采集畫面的縮放功能。傳入參數為正數,則放大焦距,傳入參數為負數則縮小焦距 double max = await livePusher.getMaxZoom(); livePusher.setZoom(min(1.0, max)); /// 手動對焦 /// [autoFocus]參數表示是否需要自動對焦,該參數僅對調用接口的該次對焦操作生效。后續是否自動對焦沿用上述自動聚焦接口設置值。 double pointX = 50.0; // 自定義數值 double pointY = 50.0; // 自定義數值 bool autoFocus = true; livePusher.focusCameraAtAdjustedPoint(pointX, pointY, autoFocus); /// 設置不打開自動對焦 livePusher.setAutoFocus(false); /// 設置不打開預覽鏡像 livePusher.setPreviewMirror(false); /// 設置不打開推流鏡像 livePusher.setPushMirror(false);
配置水印。直播推流SDK提供了添加水印功能,并且最多支持添加多個水印,水印圖片必須為PNG格式圖片。示例代碼如下:
String watermarkBundlePath = "xxxx"; //xxxx為手機存放的水印圖片資源路徑 double coordX = 0.1; double coordY = 0.1; double width = 0.3; /// 添加水印 livePusher.addWatermark(watermarkBundlePath, coordX, coordY, width);
說明coordX、coordY、width為相對值,例如coordX:0.1表示水印的x值為推流畫面x軸的10%位置,如果推流分辨率為540*960,則水印x值為54。
水印圖片的高度,按照水印圖片的真實寬高與輸入的width值等比縮放。
要實現文字水印,可以先將文字轉換為圖片,再使用此接口添加水印。
為了保障水印顯示的清晰度與邊緣平滑,請您盡量使用和水印輸出尺寸相同大小的水印源圖片。如輸出視頻分辨率544*940,水印顯示的w是0.1f,則盡量使用水印源圖片寬度在544*0.1f=54.4左右。
配置外部音視頻輸入。直播推流SDK支持將外部的音視頻源輸入進行推流,比如推送一個音視頻文件。
在推流配置里面進行外部音視頻輸入配置。
/// 開啟允許外部流輸入 pusherConfig.setExternMainStream(true); /// 設置視頻數據顏色格式定義,這里設置為YUVNV21,可根據需求設置為其他格式。 pusherConfig.setExternVideoFormat(AlivcLivePushVideoFormat.YUVNV21); /// 設置音頻數據位深度格式,這里設置為S16,可根據需求設置為其他格式 pusherConfig.setExternMainStream(AlivcLivePushAudioFormat.S16);
插入外部視頻數據。
/// 只支持外部視頻yuv和rbg格式的連續buffer數據,才可以通過sendVideoData接口,發送視頻數據buffer、長度、寬高、時間戳、旋轉角度 Uint8List bufferData = xxxx; // xxxx代表Uint8List格式的連續buffer視頻數據 int width = 720; // 視頻寬度 int height = 1280; // 視頻高度 int dataSize = xxxx; // xxxx代表data數據大小 int pts = xxxx; // xxxx代表時間戳(單位微秒) int rotation = 0; // 旋轉角度 livePusher.sendVideoData(bufferData, width, height, size, pts, rotation);
插入外部音頻數據。
/// 只支持外部pcm格式的連續buffer數據,sendPCMData,發送音頻數據buffer、長度、時間戳 Uint8List bufferData = xxxx; // xxxx代表Uint8List格式的連續buffer音頻數據 int dataSize = xxxx; // xxxx代表data數據大小 int sampleRate = xxxx; // xxxx代表采樣率 int channel = 0; // 聲道數 int pts = xxxx; // xxxx代表時間戳(單位微秒) livePusher.sendPCMData(bufferData, size, sampleRate, channel, pts);