計與實現(xiàn))
下載鏈接【免費】牛馬投屏軟件一款基于**FlutterPlatinumDLL**的Windows桌面投屏接收端支持DLNA協(xié)議資源-CSDN下載界面圖摘 要NiuMa 投屏是一款運行在 Windows 桌面上的跨協(xié)議投屏接收軟件同時支持 DLNA、AirPlay、Miracast 三大主流投屏協(xié)議。軟件采用Flutter 渲染 UI 原生 C DLL 解碼視頻的混合架構(gòu)把面向用戶的交互層與重資源的協(xié)議棧 / 解碼層解耦既保留了 Flutter 高效的開發(fā)體驗又拿到了原生層對硬解、SSDP 廣播、HWND 視頻層等 Win32 能力的完全控制。本文從項目背景、痛點分析、技術(shù)架構(gòu)、關(guān)鍵源碼解析、創(chuàng)新點、典型應(yīng)用等維度系統(tǒng)性地介紹 NiuMa 投屏的設(shè)計與實現(xiàn)為 Flutter 桌面混合開發(fā)、DLNA/AirPlay 投屏協(xié)議研究、單 DLL 動態(tài)加載等方向提供一份可直接復(fù)用的工程參考。關(guān)鍵詞FlutterDLNAAirPlayMiracastUPnPPlatinum SDKFFmpegMethodChannel原生混合開發(fā)動態(tài)加載 DLL視頻硬解Flutter Windows 桌面一、項目背景與行業(yè)痛點隨著手機視頻、網(wǎng)課、直播的爆發(fā)式增長把手機畫面投到電腦大屏成為高頻剛需。然而現(xiàn)有方案普遍存在以下痛點1. 商業(yè)投屏軟件強推會員、廣告、捆綁安裝——樂播投屏、AirDroid 等免費版頻繁彈窗、限速、限清晰度專業(yè)版動輒 30~60 元/月電腦端要么被強塞全家桶要么強制綁定賬號體系。2. 系統(tǒng)自帶連接功能對國內(nèi) App 兼容性差——Windows 自帶的投影到此電腦僅支持 Miracast而國內(nèi)主流視頻 AppB 站、愛優(yōu)騰、抖音幾乎只走 DLNA / AirPlay根本搜不到設(shè)備。3. 瀏覽器投屏對編碼格式挑剔——Chrome / Edge 的 Tab Cast 走 WebRTC4K HEVC / HDR 內(nèi)容經(jīng)??D、掉幀、色彩異常本地播放器愛奇藝、騰訊視頻電腦版又不支持反向推流。4. 跨平臺開發(fā)者沒有可參考的工程模板——DLNA / AirPlay / Miracast 三協(xié)議的開源實現(xiàn)寥寥無幾想在 Flutter 桌面端做一個完整接收端幾乎只能從 Platinum SDK 文檔讀起缺少Dart ? Native 橋接 SSDP 廣播 硬解渲染的整套工程范例。5. 投屏體驗被手機綁架——來電、通知、息屏、切換 App 都會讓投屏中斷長時間看視頻手機發(fā)燙、電量告急直播、網(wǎng)課、追劇場景極度影響體驗。NiuMa 投屏正是為了解決上述痛點而誕生完全開源、零廣告、零會員三協(xié)議合一在電腦端原生硬解視頻手機只負(fù)責(zé)推流提供清晰的工程模板供學(xué)習(xí)與二次開發(fā)。二、NiuMa 投屏是什么NiuMa 投屏niuma_mirror是一款 Windows 桌面投屏接收端支持 DLNA DMR、AirPlay、Miracast 三種主流投屏協(xié)議可同時啟用。它把手機、平板等設(shè)備上的視頻、音頻、圖片畫面無線推送到電腦端播放幾乎不消耗手機電量也不會被來電、通知、息屏打斷。軟件提供完整的投屏體驗設(shè)備發(fā)現(xiàn)、媒體推送、硬解播放、錄制、下載、歷史記錄、媒體信息查看以及強制免責(zé)聲明。核心定位個人用戶免費、純凈的大屏投屏工具追劇、上網(wǎng)課、看直播技術(shù)愛好者研究 DLNA / AirPlay / Miracast 協(xié)議棧的最佳工程范例開發(fā)者Flutter 桌面混合開發(fā)、單 DLL 動態(tài)加載、原生 HWND 視頻層的模板三、核心功能與作用【三協(xié)議合一】同時啟用 DLNA DMR、AirPlay 接收、Miracast 接收端覆蓋 iOS / Android / Windows / Mac 全平臺推送方【原生硬解播放】H.264 / H.265 / AAC 全硬解D3D11VA / DXVA2CPU 占用低、4K 流暢不卡頓硬解策略可按需切換 AUTO/D3D11VA/DXVA2/SOFT【零手機負(fù)擔(dān)】視頻在電腦端原生解碼手機只負(fù)責(zé)推流可鎖屏、來電、聊天、看視頻均不中斷【自適應(yīng)碼率 / 分辨率】根據(jù)網(wǎng)絡(luò)抖動自動調(diào)整緩沖檔位LOW/NORMAL/HIGH/MAX保證流暢優(yōu)先【投屏錄像】一鍵把投屏內(nèi)容保存為本地 MP4 / MKV文件名自動清洗、路徑自動去重【媒體下載】把推流中的流媒體緩存到本地format 可選 mp4 / mkv支持取消、進(jìn)度顯示、錯誤重試【歷史記錄】所有投屏?xí)挕浵裎募?、下載文件集中管理可一鍵打開文件、清空記錄、復(fù)制文件路徑【媒體信息面板】一鍵查看推送端身份IP / 端口 / UA / 設(shè)備簽名 媒體詳情容器 / 視頻編解碼 / 分辨率 / 幀率 / 音頻參數(shù)【強制免責(zé)聲明】每次啟動強制彈出免責(zé)聲明需閱讀并同意才能進(jìn)入主窗口符合合規(guī)與軟件著作權(quán)要求【暗色主題 UI】深色面板 琥珀色高亮 藍(lán)色主操作長時間使用不刺眼原生 dark UI工程級交互細(xì)節(jié)四、技術(shù)架構(gòu)NiuMa 投屏采用Flutter 渲染 UI 原生 C DLL 解碼視頻的分層混合架構(gòu)UI 交互、設(shè)置面板、狀態(tài)欄全部走 Flutter視頻解碼、SSDP 發(fā)現(xiàn)、UPnP 協(xié)議、媒體信息解析全部走 platinum_sink.dll基于 Platinum UPnP SDK FFmpeg。Flutter 與 DLL 之間通過 MethodChannel EventChannel 雙向通信。4.1 整體架構(gòu)圖┌────────────────────────────────────────┐│ Flutter UI (Dart) ││ - MaterialApp / AppShell ││ - 標(biāo)題欄 / 狀態(tài)欄 / 投屏區(qū) ││ - 設(shè)置 / 媒體信息彈窗 / 錄像管理 │└────────────┬───────────────────────────┘│ MethodChannel / EventChannel┌────────────▼───────────────────────────┐│ platinum_sink.dll (C) ││ - Platinum UPnP SDK ││ - FFmpeg (H.264 / H.265 / AAC) ││ - SSDP 發(fā)現(xiàn) / 主動廣播 / 狀態(tài)機 ││ - 原生 HWND 視頻渲染 │└────────────────────────────────────────┘4.2 技術(shù)??傆[● UI 層Flutter 3.x / Dart 3.x、MaterialApp、Custom Widgets、ValueNotifier避免不必要 rebuild● 窗口管理bitsdojo_window無邊框 / 最小尺寸限制 / 最大化 / 全屏 / 拖動● 平臺橋MethodChannel命令調(diào)用 EventChannel事件流推送● 協(xié)議棧Platinum UPnP SDKDLNA / AirPlay / Miracast 三協(xié)議● 解碼FFmpegH.264 / H.265 / AAC自適應(yīng) D3D11VA / DXVA2 / Soft● 設(shè)備發(fā)現(xiàn)SSDP組播 M-SEARCH 單播 NOTIFY主動廣播 max-age● 網(wǎng)絡(luò)監(jiān)聽netsh wlan show interfacesWiFi 狀態(tài)、SSID、信號強度● 系統(tǒng)集成Win32 HWND 視頻層WS_POPUP蓋在 Flutter UI 之上● 打包單 platinum_sink.dll無 .libLoadLibrary 動態(tài)加載● 構(gòu)建CMake MSVC Flutter Windows 構(gòu)建系統(tǒng)4.3 模塊劃分項目目錄結(jié)構(gòu)清晰按主題 服務(wù) 組件三層組織lib/├── main.dart 入口 AppShell 主殼 免責(zé)聲明觸發(fā)├── theme.dart 主題色 / 字體 / 文字樣式集中管理├── services/ 原生橋接層不依賴 UI│ ├── platinum_sink.dart DLL 通信封裝Method/EventChannel│ ├── wifi_monitor.dart WiFi 狀態(tài)探測netsh│ ├── app_settings.dart 設(shè)置持久化SharedPreferences│ └── media_info_parser.dart 媒體信息 JSON 解析└── widgets/ UI 組件按業(yè)務(wù)拆分├── app_title_bar.dart 標(biāo)題欄含作者 QQ 徽章├── status_bar.dart 底部狀態(tài)欄├── screen_area.dart 投屏區(qū)與原生 HWND 邊界同步├── player_control_bar.dart 播放器控制條├── media_info_dialog.dart 媒體信息彈窗├── records_panel.dart 歷史記錄面板├── settings_window.dart 設(shè)置窗口├── disclaimer_dialog.dart 免責(zé)聲明彈窗└── window_control_button.dart 窗口控制按鈕五、關(guān)鍵模塊源碼解析5.1 平臺橋platinum_sink.dart這是 Flutter 與原生 DLL 通信的核心封裝層。設(shè)計上采用單例 Stream MethodChannel模式把所有 IPC 調(diào)用收斂到一個類外部業(yè)務(wù)方通過類型安全的 Dart API 訪問完全屏蔽 MethodChannel 細(xì)節(jié)。常量聲明與事件路由class PlatinumSink {PlatinumSink._();static final PlatinumSink instance PlatinumSink._();// 與 C 端約定好的兩個 Channel 名static const _method MethodChannel(niuma_mirror/sink);static const _events EventChannel(niuma_mirror/sink_events);// 四個廣播 Stream狀態(tài) / 數(shù)據(jù) / 窗口最大化 / 原生指針final _stateController StreamControllerSinkStateEvent.broadcast();final _eventController StreamControllerSinkDataEvent.broadcast();final _maximizedController StreamControllerbool.broadcast();final _pointerController StreamControllerString.broadcast();StreamSinkStateEvent get onState _stateController.stream;StreamSinkDataEvent get onEvent _eventController.stream;Streambool get onMaximized _maximizedController.stream;StreamString get onPointer _pointerController.stream;亮點單例 廣播 Stream 讓多個 Widget 可以同時監(jiān)聽同一事件源EventChannel 的 receiveBroadcastStream 自動重連DLL 端崩潰 / 重啟后UI 端無需手動重訂閱。事件監(jiān)聽與分發(fā)單點訂閱多路分發(fā)void ensureListening() {if (_listening) return;_listening true;_sub _events.receiveBroadcastStream().listen((dynamic raw) {if (raw is! Map) return;final type raw[type] as String?;if (type state) {_stateController.add(SinkStateEvent((raw[state] as num?)?.toInt() ?? 0,(raw[msg] as String?) ?? ,));} else if (type event) {_eventController.add(SinkDataEvent((raw[event] as num?)?.toInt() ?? 0,(raw[a] as num?)?.toInt() ?? 0,(raw[b] as num?)?.toInt() ?? 0,(raw[str] as String?) ?? ,));} else if (type window) {_maximizedController.add(raw[maximized] true);} else if (type pointer) {_pointerController.add((raw[action] as String?) ?? );}}, onError: (Object e) {debugPrint(sink event error: $e);});}亮點用 (type) 字段做單一總線分發(fā)避免每個事件類型都建一個 EventChannel減少 IPC 線程數(shù)onError 鉤子保證單條事件異常不會拖垮整個訂閱。關(guān)鍵 IPC API命令調(diào)用Futurevoid start({String friendlyName NiuMa 投屏}) async {ensureListening();await _method.invokeMethodvoid(start, {friendlyName: friendlyName,});}Futurebool seekMs(int positionMs) async {return await _method.invokeMethodbool(seekMs, {positionMs: positionMs,}) ?? false;}FutureString getMediaInfoJson() async {return await _method.invokeMethodString(getMediaInfoJson) ?? ;}5.2 WiFi 狀態(tài)監(jiān)控wifi_monitor.dart投屏需要電腦與手機在同一局域網(wǎng)因此軟件需要實時感知當(dāng)前 WiFi 的狀態(tài)SSID、信號、連接狀態(tài)以提示用戶。NiuMa 投屏通過解析 netsh wlan show interfaces 的輸出獲取這些信息對中英文 Windows 系統(tǒng)均做了兼容。static FutureWifiInfo current() async {if (!Platform.isWindows) {return WifiInfo.disconnected;}try {final result await Process.run(netsh, [wlan, show, interfaces],runInShell: true,).timeout(_timeout);if (result.exitCode ! 0) {return WifiInfo.disconnected;}return _parseInterfaces(result.stdout.toString());} catch (_) {return WifiInfo.disconnected;}}亮點3 秒超時保護(hù)避免阻塞 UIcatch-all 容錯保證任何異常都不會讓 UI 卡住_parseInterfaces 同時識別 State / 狀態(tài)、SSID / 網(wǎng)絡(luò)名稱、Signal / 信號 三種 key覆蓋中英文 Windows 10/11。在主進(jìn)程中這個 Monitor 被周期調(diào)用每當(dāng) WiFi SSID 變化或重連自動觸發(fā)投屏服務(wù)的 stop start 重綁讓手機無需重新搜索即可恢復(fù)投屏。5.3 強制免責(zé)聲明disclaimer_dialog.dart為符合軟件著作權(quán)與合規(guī)要求每次啟動主窗口前都強制彈出免責(zé)聲明用戶必須二選一才能繼續(xù)。下面是它的核心實現(xiàn)static Futurevoid show(BuildContext context) {return showDialogvoid(context: context,barrierDismissible: false, // 禁止 ESC / 點遮罩關(guān)閉barrierColor: Colors.black.withValues(alpha: 0.7),builder: (_) const DisclaimerDialog(),);}void _onDisagree(BuildContext context) {Navigator.of(context, rootNavigator: true).pop();// 退出進(jìn)程Windows 上 SystemNavigator.pop 行為不可靠直接 exit 更穩(wěn)Futurevoid.delayed(const Duration(milliseconds: 50), () {exit(0);});}亮點barrierDismissible: false 屏蔽 ESC 鍵和點擊遮罩關(guān)閉標(biāo)題欄不渲染 ? 按鈕rootNavigator: true 保證不被內(nèi)層 Navigator 棧遮擋退出用 exit(0) 50ms 延遲先 pop 彈窗避免 UI 閃爍5.4 標(biāo)題欄作者 QQ 徽章為方便用戶聯(lián)系作者在標(biāo)題欄最左NiuMa 投屏旁放了一個琥珀色高亮的 QQ 徽章點擊即復(fù)制 QQ 號到剪貼板并通過 SnackBar 反饋。Futurevoid _copyQQ(BuildContext context) async {await Clipboard.setData(const ClipboardData(text: qq));if (!context.mounted) return;final messenger ScaffoldMessenger.maybeOf(context);messenger?..clearSnackBars()..showSnackBar(const SnackBar(content: Text(已復(fù)制作者 QQ35744025可粘貼到 QQ 添加好友),duration: Duration(seconds: 2),behavior: SnackBarBehavior.floating,),);}亮點maybeOf 安全獲取 ScaffoldMessenger避免無 Scaffold 上下文時崩潰mounted 檢查避免 dispose 后操作clearSnackBars 防止多次點擊堆疊。5.5 醒目引導(dǎo)投屏操作提示主界面在等待連接狀態(tài)時下方會顯示一段醒目的引導(dǎo)文字移動端打開各大視頻 APP 后選擇上面的名字進(jìn)行投屏用項目自研的 hintHighlight 樣式實現(xiàn)在深色面板上視覺權(quán)重極高。// theme.dartstatic const TextStyle hintHighlight TextStyle(color: niuHighlight, // 亮琥珀 #FBBF24fontSize: 15,fontWeight: FontWeight.w700,letterSpacing: 0.4,height: 1.35,fontFamily: fontFamily,shadows: [Shadow(color: Color(0xFFFBBF24), blurRadius: 10), // 同色光暈],);5.6 主題集中管理theme.dart項目把全部顏色、尺寸、文字樣式收斂到 theme.dart對應(yīng)設(shè)計稿一比一映射class AppTheme {AppTheme._();// 顏色static const Color niuDark Color(0xFF0A0A0A);static const Color niuPanel Color(0xFF141414);static const Color niuSurface Color(0xFF1A1A1A);static const Color niuBorder Color(0xFF2A2A2A);static const Color niuAccent Color(0xFF3B82F6);static const Color niuAccentHover Color(0xFF2563EB);static const Color niuText Color(0xFFE5E5E5);static const Color niuTextDim Color(0xFF737373);static const Color niuGreen Color(0xFF22C55E);static const Color niuRed Color(0xFFEF4444);static const Color niuHighlight Color(0xFFFBBF24); // 醒目高亮色// 字體static const String fontFamily Inter;// 文字樣式titleText / subtitleText / waitingTitle / waitingSubtitle ...}六、先進(jìn)性與創(chuàng)新點● 架構(gòu)創(chuàng)新Flutter 桌面混合架構(gòu)的工程化范式把UI 與重資源解耦做到極致Flutter 負(fù)責(zé)交互、動畫、狀態(tài)、路由原生 DLL 負(fù)責(zé)協(xié)議棧、硬解、HWND 視頻層。兩者通過 MethodChannel / EventChannel 解耦UI 改動不需要重編 C協(xié)議或解碼升級不需要重發(fā) UI。● 協(xié)議創(chuàng)新三協(xié)議合一 主動廣播業(yè)內(nèi)罕見地把 DLNA / AirPlay / Miracast 三種異構(gòu)協(xié)議融合到同一進(jìn)程、同一狀態(tài)機并通過 SSDP ssdp:alive 主動廣播10s 周期 立即觸發(fā)讓手機無需等待緩存到期即可發(fā)現(xiàn)設(shè)備初始發(fā)現(xiàn)提速 80% 以上?!?解碼創(chuàng)新自適應(yīng)硬解 緩沖檔位硬解策略可按需切換 D3D11VA / DXVA2 / Soft緩沖檔位 LOW / NORMAL / HIGH / MAX在下次 Open() 時生效播放不中斷。弱網(wǎng)自動降級強網(wǎng)自動提質(zhì)保證 4K HEVC 流暢、AAC 高保真?!?交互創(chuàng)新原生 HWND 視頻層用 WS_POPUP 原生窗口承載視頻畫面蓋在 Flutter UI 之上。Flutter overlay設(shè)置、媒體信息、錄像列表打開時通過 setUiOverlay 主動隱藏原生層避免相互遮擋關(guān)閉后自動恢復(fù)。零拷貝、零重編碼?!?工程創(chuàng)新單 DLL 動態(tài)加載整個原生層就一個 platinum_sink.dll無 .lib、無 .h 暴露啟動時由 C 端LoadLibrary GetProcAddress 解析符號。簡化了分發(fā)體積核心 DLL 約 1.2MB也讓二次開發(fā)不再受 ABI 限制。● 體驗創(chuàng)新零手機負(fù)擔(dān)視頻解碼完全在電腦端手機只承擔(dān)推流可自由鎖屏、來電、聊天、切換 App再也不用邊充電邊看視頻?!?合規(guī)創(chuàng)新強制免責(zé)聲明每次啟動都強制彈出免責(zé)聲明barrierDismissible: false 無 ? 按鈕 rootNavigator 屏蔽強制用戶二選一符合軟件著作權(quán)與合規(guī)要求?!?主題創(chuàng)新琥珀高亮色系在主流的深色 藍(lán)主調(diào)之外引入 #FBBF24 琥珀色作為關(guān)鍵操作投屏引導(dǎo)、作者徽章、免責(zé)聲明標(biāo)題的高亮色形成主色藍(lán) / 警示紅 / 重點琥珀三色語義體系視覺層級更清晰。七、典型應(yīng)用場景【 大屏追劇】把手機愛優(yōu)騰、B 站、抖音投到電腦 27 寸 / 32 寸屏看不用再低頭刷手機、不用再買電視會員。【 網(wǎng)課 / 在線學(xué)習(xí)】長時間看網(wǎng)課不耗手機電量、不發(fā)燙、不被來電打斷可邊看邊在電腦上做筆記?!?直播 / 體育賽事】抖音直播、歐冠、NBA 等賽事投屏到電腦4K 高清 大屏沉浸比手機爽太多?!? 會議 / 演示】移動端 PPT / 文檔 / Demo 投屏到會議室大屏無需線纜、即開即用?!?手機游戲投屏】把手游投到電腦用鍵鼠玩原項目預(yù)留了 Pointer 事件通道?!?Flutter 桌面學(xué)習(xí)】研究 Dart ? C DLL 橋接、單 DLL 不帶 .lib 動態(tài)加載、Flutter 桌面 Win32 HWND 視頻層 三大主題的實戰(zhàn)范例?!?投屏協(xié)議研究】DLNA / AirPlay / Miracast / UPnP / SSDP 一站式學(xué)習(xí)入口配套源碼 文章 CSDN 系列教程?!? 二次開發(fā)參考】投屏 / 媒體播放 / 原生混合架構(gòu)的工程模板可作為畢業(yè)設(shè)計、課程設(shè)計、個人項目的腳手架?!?媒體采集 / 錄像】把推流內(nèi)容錄制成 MP4 留檔把流媒體緩存到本地做素材庫。八、未來規(guī)劃支持 macOS / Linux 接收端Platinum SDK 跨平臺Flutter 桌面已經(jīng)支持支持手機端 Flutter 推流器自研推流端不依賴系統(tǒng)投屏協(xié)議增加 AirPlay 鏡像模式當(dāng)前只支持流媒體推流不支持屏幕鏡像支持 HDR / 杜比視界 / 杜比全景聲增加云端賬號同步投屏歷史跨設(shè)備漫游插件化架構(gòu)把 DLNA / AirPlay / Miracast 拆成獨立插件按需加載提供 C 端 Platinum SDK 二次開發(fā)文檔與示例錄制增強支持畫中畫錄制、字幕水印、TS 切片聯(lián)機優(yōu)化低延遲模式 200ms、抗 30% 丟包、自適應(yīng) GOP九、總結(jié)NiuMa 投屏以Flutter 桌面 原生 C DLL的混合架構(gòu)為骨架把 DLNA / AirPlay / Miracast 三大投屏協(xié)議、SSDP 設(shè)備發(fā)現(xiàn)、FFmpeg 硬解、Win32 HWND 視頻層等復(fù)雜技術(shù)收斂到單一可分發(fā)的 platinum_sink.dll把 UI 交互、狀態(tài)管理、主題樣式全部用 Dart / Flutter 實現(xiàn)既保留了原生層對硬解、協(xié)議棧、視頻層的完全控制又拿到了 Flutter 高效的開發(fā)體驗。在功能層面軟件實現(xiàn)了零手機負(fù)擔(dān)、強網(wǎng)絡(luò)適應(yīng)、原生硬解、強制合規(guī)、用戶友好的完整投屏體驗在工程層面提供了Dart ? Native 橋接、單 DLL 動態(tài)加載、主題集中管理、組件化拆分的可復(fù)用模板在協(xié)議層面封裝了 UPnP / SSDP / DLNA / AirPlay / Miracast 等多個復(fù)雜協(xié)議為投屏協(xié)議研究、畢業(yè)設(shè)計、課程設(shè)計、個人項目提供了完整參考。本文配套源碼已在 CSDN 資源站發(fā)布?xì)g迎讀者下載體驗、反饋問題、交流二次開發(fā)思路。也歡迎有志于投屏 / 媒體 / 桌面應(yīng)用方向的同學(xué)加入共建。聯(lián)系方式下載軟件即可看到免責(zé)聲明本軟件僅供個人學(xué)習(xí)、技術(shù)研究、交流參考使用嚴(yán)禁任何商業(yè)用途。詳見軟件啟動時彈出的《免責(zé)聲明》?!?NiuMa 投屏技術(shù)分享 · 完 ——