翻譯|使用教程|編輯:吉煒煒|2024-11-14 14:56:20.460|閱讀 96 次
概述:在本文中,我們將展示如何利用 JxBrowser 的功能在兩個(gè) Compose Desktop 應(yīng)用程序之間實(shí)現(xiàn)屏幕共享。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
JxBrowser是一個(gè)跨平臺(tái)的 JVM 庫(kù),它允許您將基于 Chromium 的 Browser 控件集成到 Compose、Swing、JavaFX、SWT 應(yīng)用程序中,并使用 Chromium 的數(shù)百種功能。為了在 Kotlin 中實(shí)現(xiàn)屏幕共享,我們利用了 Chromium 的 WebRTC 支持以及 JxBrowser 對(duì)其的編程訪問(wèn)能力。
在本文中,我們將展示如何利用 JxBrowser 的功能在兩個(gè) Compose Desktop 應(yīng)用程序之間實(shí)現(xiàn)屏幕共享。
概述
WebRTC 是一個(gè)開(kāi)放標(biāo)準(zhǔn),允許通過(guò)常規(guī) JavaScript API 進(jìn)行實(shí)時(shí)通信。該技術(shù)在所有現(xiàn)代 Browser 以及所有主要平臺(tái)的原生客戶端上均可使用。我們將使用它將捕獲的屏幕視頻流從一個(gè)應(yīng)用程序發(fā)送到另一個(gè)應(yīng)用程序。
該項(xiàng)目由四個(gè)模塊組成:
信令服務(wù)器促進(jìn)對(duì)等端之間初始的連接信息交換。這包括有關(guān)網(wǎng)絡(luò)、會(huì)話描述符和媒體功能的信息。
Compose 客戶端是兩個(gè)桌面應(yīng)用程序:一個(gè)通過(guò)單擊即可共享屏幕,另一個(gè)接收并顯示視頻流。
服務(wù)器
WebRTC 的主要挑戰(zhàn)之一是如何管理信令,它充當(dāng)對(duì)等端的匯合點(diǎn),而不傳輸實(shí)際數(shù)據(jù)。我們使用 PeerJS 庫(kù)來(lái)抽象信令邏輯,使我們能夠?qū)W⒂趹?yīng)用程序的功能。該庫(kù)提供了服務(wù)器和客戶端實(shí)現(xiàn)。
我們需要做的只是創(chuàng)建一個(gè) PeerServer 實(shí)例并運(yùn)行創(chuàng)建的 Node.js 應(yīng)用程序。
首先,我們添加所需的 NPM 依賴項(xiàng):
npm install peer
然后,創(chuàng)建一個(gè) PeerServer 實(shí)例:
PeerServer({ port: 3000 });
并運(yùn)行創(chuàng)建的應(yīng)用程序:
node server.js
Compose 客戶端
對(duì)于 Compose 應(yīng)用程序,我們需要使用 JxBrowser 和 Compose 插件來(lái)初始化一個(gè)空的 Gradle 項(xiàng)目:
plugins { id("org.jetbrains.kotlin.jvm") version "2.0.0" id("com.teamdev.jxbrowser") version "1.1.0" id("org.jetbrains.compose") version "1.6.11" } jxbrowser { version = "8.1.0" includePreviewBuilds() } dependencies { implementation(jxbrowser.currentPlatform) implementation(jxbrowser.compose) implementation(compose.desktop.currentOs) }
每個(gè) Compose 客戶端由三層組成:
接收端應(yīng)用程序
讓我們先從顯示共享屏幕的接收端應(yīng)用程序開(kāi)始。
我們需要實(shí)現(xiàn)一個(gè)接收 WebRTC 組件。它應(yīng)該連接到信令服務(wù)器并訂閱傳入的呼叫。其 API 將由一個(gè)單獨(dú)的 connect() 函數(shù)組成。該函數(shù)應(yīng)暴露在全局范圍內(nèi),以便從 Kotlin 端進(jìn)行訪問(wèn)。
window.connect = (signalingServer) => { const peer = new Peer(RECEIVER_PEER_ID, signalingServer); peer.on('call', (call) => { call.answer(); call.on('stream', (stream) => { showVideo(stream); }); call.on('close', () => { hideVideo(); }); }); }
我們接聽(tīng)每個(gè)呼叫,并在 <video> 元素中顯示接收到的流,否則該元素將被隱藏。在文章的末尾,我們會(huì)提供一個(gè)指向 GitHub 上完整源代碼的鏈接。
接下來(lái),我們將使用 JxBrowser 加載此組件,并使暴露的 JS 函數(shù)可以從 Kotlin 中調(diào)用:
class WebrtcReceiver(browser: Browser) { private const val webrtcComponent = "/receiving-peer.html" private val frame = browser.mainFrame!! init { browser.loadWebPage(webrtcComponent) } fun connect(server: SignalingServer) = executeJavaScript("connect($server)") // 在加載的 Frame 上執(zhí)行給定的 JS 代碼。 private fun executeJavaScript(javaScript: String) = // ... // 從應(yīng)用程序的資源中加載頁(yè)面。 private fun Browser.loadWebPage(webPage: String) = // ... }
WebrtcReceiver 從應(yīng)用程序的資源中加載實(shí)現(xiàn)的組件到 Browser 中,并公開(kāi)一個(gè)單一的公共 connect(...) 方法,該方法直接調(diào)用其 JS 對(duì)應(yīng)項(xiàng)。
最后,讓我們創(chuàng)建一個(gè) Compose 應(yīng)用程序來(lái)將這些組件組合在一起:
singleWindowApplication(title = "Screen Viewer") { val engine = remember { createEngine() } val browser = remember { engine.newBrowser() } val webrtc = remember { WebrtcReceiver(browser) } BrowserView(browser) LaunchedEffect(Unit) { webrtc.connect(SIGNALING_SERVER) } }
首先,我們創(chuàng)建 Engine、Browser 和 WebrtcReceiver 實(shí)例。然后,我們添加 BrowserView 組合項(xiàng)來(lái)顯示 HTML5 視頻播放器。在啟動(dòng)的效果中,我們連接到信令服務(wù)器,假設(shè)這是一個(gè)快速且不會(huì)失敗的操作。
發(fā)送端應(yīng)用程序
在發(fā)送端應(yīng)用程序中,我們通過(guò)向接收端發(fā)起呼叫來(lái)共享主屏幕。
我們需要實(shí)現(xiàn)發(fā)送 WebRTC 組件。它應(yīng)該能夠連接到信令服務(wù)器,開(kāi)始和停止屏幕共享會(huì)話。因此,它的 API 將由三個(gè)函數(shù)組成。這些函數(shù)應(yīng)該暴露給全局作用域,以便從 Kotlin 端進(jìn)行訪問(wèn)。
let peer; let mediaConnection; let mediaStream; window.connect = (signalingServer) => { peer = new Peer(SENDER_PEER_ID, signalingServer); } window.startScreenSharing = () => { navigator.mediaDevices.getDisplayMedia({ video: {cursor: 'always'} }).then(stream => { mediaConnection = peer.call(RECEIVER_PEER_ID, stream); mediaStream = stream; }); } window.stopScreenSharing = () => { mediaConnection.close(); mediaStream.getTracks().forEach(track => track.stop()); }
在建立與信令服務(wù)器的連接后,組件可以開(kāi)始和停止屏幕共享會(huì)話。開(kāi)始新的會(huì)話意味著選擇一個(gè)媒體流來(lái)呼叫接收端。當(dāng)共享停止時(shí),應(yīng)該關(guān)閉該流和點(diǎn)對(duì)點(diǎn)媒體連接。只要組件被加載,與信令服務(wù)器的連接就會(huì)保持活動(dòng)狀態(tài)。
與接收端應(yīng)用程序類似,讓我們?yōu)檫@個(gè)組件創(chuàng)建一個(gè) Kotlin 包裝器。我們將通過(guò)添加新功能來(lái)擴(kuò)展 WebrtcReceiver 以創(chuàng)建 WebrtcSender。
首先,我們需要告訴 JxBrowser 使用哪個(gè)視頻源。默認(rèn)情況下,當(dāng)網(wǎng)頁(yè)想要從屏幕捕獲視頻時(shí),Chromium 會(huì)顯示一個(gè)對(duì)話框,我們可以在其中選擇源。使用 JxBrowser API,我們可以直接在代碼中指定捕獲源:
init { // 當(dāng) Browser 即將開(kāi)始捕獲會(huì)話時(shí),選擇一個(gè)源。 browser.register(StartCaptureSessionCallback { params: Params, tell: Action -> val primaryScreen = params.sources().screens()[0] tell.selectSource(primaryScreen, AudioCaptureMode.CAPTURE) }) }
其次,我們希望讓用戶界面知道當(dāng)前是否有活動(dòng)的共享會(huì)話。這是為了決定是顯示 Start 還是 Stop 按鈕。讓我們創(chuàng)建一個(gè)可觀察的屬性,并將其綁定到 JxBrowser 的 CaptureSessionStarted 和 CaptureSessionsStopped 事件:
var isSharing by mutableStateOf(false) private set init { // ... // 在會(huì)話開(kāi)始和停止時(shí)更新 `isSharing` 狀態(tài)變量。 browser.subscribe<CaptureSessionStarted> { event: CaptureSessionStarted -> isSharing = true event.capture().subscribe<CaptureSessionStopped> { isSharing = false } } }
最后要做的就是添加兩個(gè)公共方法,用于調(diào)用其 JavaScript 對(duì)應(yīng)項(xiàng):
fun startScreenSharing() = executeJavaScript("startScreenSharing()") fun stopScreenSharing() = executeJavaScript("stopScreenSharing()")
就是這樣!
在本地運(yùn)行時(shí),應(yīng)用程序看起來(lái)是這樣的:
在不同的 PC 上運(yùn)行
作為一項(xiàng)額外的好處,您可以輕松地使此示例在不同的 PC 上運(yùn)行,而無(wú)需暴露本地運(yùn)行的信令服務(wù)器。PeerJS 提供了一個(gè)免費(fèi)的云托管 PeerServer 版本。如果未指定特定的服務(wù)器來(lái)使用,該庫(kù)將自動(dòng)連接到公共云服務(wù)器。請(qǐng)注意,在編寫本文時(shí),它是可運(yùn)行的,但其正常運(yùn)行時(shí)間并不保證。
要嘗試此功能,您需要在發(fā)送和接收 WebRTC 組件中刪除顯式傳遞給 Peer 構(gòu)造函數(shù)的服務(wù)器參數(shù)。
// 使用該服務(wù)器。 const peer = new Peer(RECEIVER_PEER_ID, signalingServer); // 使用云托管實(shí)例。 const peer = new Peer(RECEIVER_PEER_ID);
另外,請(qǐng)注意,您將與其他人共享這個(gè)公共服務(wù)器,由于對(duì)等 ID 是手動(dòng)設(shè)置的,所以可能會(huì)發(fā)生沖突。
結(jié)論
在本文中,我們展示了如何使用 JxBrowser 和 WebRTC 在一個(gè) Compose 應(yīng)用程序中共享屏幕,并在另一個(gè)應(yīng)用程序中顯示視頻流。通過(guò)利用 JxBrowser 對(duì) Chromium 的集成以及用于 WebRTC 的 PeerJS 庫(kù),我們可以快速構(gòu)建一個(gè)功能完備的屏幕共享應(yīng)用程序。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:慧都網(wǎng)