翻譯|使用教程|編輯:吉煒煒|2024-11-14 14:56:20.460|閱讀 108 次
概述:在本文中,我們將展示如何利用 JxBrowser 的功能在兩個 Compose Desktop 應用程序之間實現屏幕共享。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
JxBrowser是一個跨平臺的 JVM 庫,它允許您將基于 Chromium 的 Browser 控件集成到 Compose、Swing、JavaFX、SWT 應用程序中,并使用 Chromium 的數百種功能。為了在 Kotlin 中實現屏幕共享,我們利用了 Chromium 的 WebRTC 支持以及 JxBrowser 對其的編程訪問能力。
在本文中,我們將展示如何利用 JxBrowser 的功能在兩個 Compose Desktop 應用程序之間實現屏幕共享。
概述
WebRTC 是一個開放標準,允許通過常規 JavaScript API 進行實時通信。該技術在所有現代 Browser 以及所有主要平臺的原生客戶端上均可使用。我們將使用它將捕獲的屏幕視頻流從一個應用程序發送到另一個應用程序。
該項目由四個模塊組成:
信令服務器促進對等端之間初始的連接信息交換。這包括有關網絡、會話描述符和媒體功能的信息。
	Compose 客戶端是兩個桌面應用程序:一個通過單擊即可共享屏幕,另一個接收并顯示視頻流。 
 
服務器
WebRTC 的主要挑戰之一是如何管理信令,它充當對等端的匯合點,而不傳輸實際數據。我們使用 PeerJS 庫來抽象信令邏輯,使我們能夠專注于應用程序的功能。該庫提供了服務器和客戶端實現。
我們需要做的只是創建一個 PeerServer 實例并運行創建的 Node.js 應用程序。
首先,我們添加所需的 NPM 依賴項:
npm install peer
然后,創建一個 PeerServer 實例:
PeerServer({
    port: 3000
});
并運行創建的應用程序:
node server.js
Compose 客戶端
對于 Compose 應用程序,我們需要使用 JxBrowser 和 Compose 插件來初始化一個空的 Gradle 項目:
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)
}
每個 Compose 客戶端由三層組成:
接收端應用程序
讓我們先從顯示共享屏幕的接收端應用程序開始。
我們需要實現一個接收 WebRTC 組件。它應該連接到信令服務器并訂閱傳入的呼叫。其 API 將由一個單獨的 connect() 函數組成。該函數應暴露在全局范圍內,以便從 Kotlin 端進行訪問。
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();
        });
    });
}
我們接聽每個呼叫,并在 <video> 元素中顯示接收到的流,否則該元素將被隱藏。在文章的末尾,我們會提供一個指向 GitHub 上完整源代碼的鏈接。
接下來,我們將使用 JxBrowser 加載此組件,并使暴露的 JS 函數可以從 Kotlin 中調用:
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 上執行給定的 JS 代碼。
    private fun executeJavaScript(javaScript: String) = // ...
    // 從應用程序的資源中加載頁面。
    private fun Browser.loadWebPage(webPage: String) = // ...
}
WebrtcReceiver 從應用程序的資源中加載實現的組件到 Browser 中,并公開一個單一的公共 connect(...) 方法,該方法直接調用其 JS 對應項。
最后,讓我們創建一個 Compose 應用程序來將這些組件組合在一起:
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)
    }
}
首先,我們創建 Engine、Browser 和 WebrtcReceiver 實例。然后,我們添加 BrowserView 組合項來顯示 HTML5 視頻播放器。在啟動的效果中,我們連接到信令服務器,假設這是一個快速且不會失敗的操作。
發送端應用程序
在發送端應用程序中,我們通過向接收端發起呼叫來共享主屏幕。
我們需要實現發送 WebRTC 組件。它應該能夠連接到信令服務器,開始和停止屏幕共享會話。因此,它的 API 將由三個函數組成。這些函數應該暴露給全局作用域,以便從 Kotlin 端進行訪問。
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());
}
在建立與信令服務器的連接后,組件可以開始和停止屏幕共享會話。開始新的會話意味著選擇一個媒體流來呼叫接收端。當共享停止時,應該關閉該流和點對點媒體連接。只要組件被加載,與信令服務器的連接就會保持活動狀態。
與接收端應用程序類似,讓我們為這個組件創建一個 Kotlin 包裝器。我們將通過添加新功能來擴展 WebrtcReceiver 以創建 WebrtcSender。
首先,我們需要告訴 JxBrowser 使用哪個視頻源。默認情況下,當網頁想要從屏幕捕獲視頻時,Chromium 會顯示一個對話框,我們可以在其中選擇源。使用 JxBrowser API,我們可以直接在代碼中指定捕獲源:
init {
    // 當 Browser 即將開始捕獲會話時,選擇一個源。
    browser.register(StartCaptureSessionCallback { params: Params, tell: Action ->
        val primaryScreen = params.sources().screens()[0]
        tell.selectSource(primaryScreen, AudioCaptureMode.CAPTURE)
    })
}
其次,我們希望讓用戶界面知道當前是否有活動的共享會話。這是為了決定是顯示 Start 還是 Stop 按鈕。讓我們創建一個可觀察的屬性,并將其綁定到 JxBrowser 的 CaptureSessionStarted 和 CaptureSessionsStopped 事件:
var isSharing by mutableStateOf(false)
    private set
init {
    // ...
    // 在會話開始和停止時更新 `isSharing` 狀態變量。
    browser.subscribe<CaptureSessionStarted> { event: CaptureSessionStarted ->
        isSharing = true
        event.capture().subscribe<CaptureSessionStopped> {
            isSharing = false
        }
    }
}
最后要做的就是添加兩個公共方法,用于調用其 JavaScript 對應項:
fun startScreenSharing() = executeJavaScript("startScreenSharing()")
fun stopScreenSharing() = executeJavaScript("stopScreenSharing()")
就是這樣!
在本地運行時,應用程序看起來是這樣的:
 
 
在不同的 PC 上運行
作為一項額外的好處,您可以輕松地使此示例在不同的 PC 上運行,而無需暴露本地運行的信令服務器。PeerJS 提供了一個免費的云托管 PeerServer 版本。如果未指定特定的服務器來使用,該庫將自動連接到公共云服務器。請注意,在編寫本文時,它是可運行的,但其正常運行時間并不保證。
要嘗試此功能,您需要在發送和接收 WebRTC 組件中刪除顯式傳遞給 Peer 構造函數的服務器參數。
// 使用該服務器。 const peer = new Peer(RECEIVER_PEER_ID, signalingServer); // 使用云托管實例。 const peer = new Peer(RECEIVER_PEER_ID);
另外,請注意,您將與其他人共享這個公共服務器,由于對等 ID 是手動設置的,所以可能會發生沖突。
結論
在本文中,我們展示了如何使用 JxBrowser 和 WebRTC 在一個 Compose 應用程序中共享屏幕,并在另一個應用程序中顯示視頻流。通過利用 JxBrowser 對 Chromium 的集成以及用于 WebRTC 的 PeerJS 庫,我們可以快速構建一個功能完備的屏幕共享應用程序。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉載自:慧都網