基於 Golang 和 WebSocket 實現屏幕共享方案
在遠程協作、在線教學、監控等場景中(當然啦!還有其他的用途,這裏就不說了,懂得都懂),屏幕共享是一項非常重要的技術。本文將介紹如何使用 Golang 開發一個基於 WebSocket 的屏幕共享系統,實現遠程查看電腦屏幕的功能。
技術原理
整個屏幕共享的流程如下:
-
定時截圖:使用
kbinani/screenshot
進行屏幕捕獲,每隔 100ms 採集一次屏幕。 -
圖片壓縮:爲了減少數據傳輸量,將截圖壓縮爲
JPEG
格式。 -
WebSocket 傳輸:通過
gorilla/websocket
實現 WebSocket 服務器,將截圖數據推送給瀏覽器客戶端。 -
前端展示:瀏覽器通過
WebSocket
接收圖像數據,並動態更新img
標籤以實時顯示共享的屏幕內容。
後端實現
我們首先創建一個 go 項目並使用 go 編寫一個 WebSocket 服務器,用於捕獲屏幕並實時發送給客戶端,具體操作如下所示:
mkdir websocket-demo
cd websocket-demo/ && go mod init websocket-demo
# 安裝 WebSocket 庫
go get -u github.com/gorilla/websocket
# 安裝屏幕截圖庫
go get -u github.com/kbinani/screenshot
然後鍵入如下代碼,具體如下所示:
package main
import (
"bytes"
"fmt"
"image/jpeg"
"net/http"
"time"
"github.com/gorilla/websocket"
"github.com/kbinani/screenshot"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 允許跨域
}
// 捕獲屏幕並轉換爲JPEG
func captureScreen() ([]byte, error) {
img, err := screenshot.CaptureDisplay(0) // 僅截取主屏幕
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
jpeg.Encode(buf, img, &jpeg.Options{Quality: 50}) // 50% 質量壓縮
return buf.Bytes(), nil
}
// 處理WebSocket連接
func handleWS(conn *websocket.Conn) {
defer conn.Close()
for {
time.Sleep(100 * time.Millisecond) // 每100ms發送一次(10FPS)
imgData, err := captureScreen()
if err != nil {
fmt.Println("截圖失敗:", err)
continue
}
// 發送圖片數據
if err = conn.WriteMessage(websocket.BinaryMessage, imgData); err != nil {
fmt.Println("發送失敗:", err)
break
}
}
}
func main() {
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("WebSocket連接失敗:", err)
return
}
go handleWS(conn) // 處理WebSocket連接
})
fmt.Println("WebSocket 服務器啓動,訪問 ws://localhost:9527/ws")
http.ListenAndServe(":9527", nil)
}
代碼解析
-
screenshot.CaptureDisplay(0):獲取主屏幕的截圖。
-
jpeg.Encode(buf, img, &jpeg.Options{Quality: 50}):將圖片轉換爲
JPEG
格式並壓縮,減少數據傳輸量。 -
websocket.Upgrader:用於升級 HTTP 連接爲 WebSocket 連接。
-
handleWS(conn)
:不斷循環截圖併發送給 WebSocket 客戶端。
⚠️注意: 需要提前安裝好 opencv 相關依賴
前端實現
前端需要使用 WebSocket 接收屏幕圖像數據,並動態更新img
標籤,具體事項如下所示:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>屏幕共享</title>
</head>
<body>
<h2>實時屏幕共享</h2>
<img id="screen" style="border: 1px solid black; width: 80%; max-width: 1024px;">
<script>
let ws = new WebSocket("ws://localhost:9527/ws");
let img = document.getElementById("screen");
ws.binaryType = "blob";
ws.onmessage = function (event) {
let url = URL.createObjectURL(event.data);
img.src = url;
};
ws.onclose = function () {
alert("連接已斷開");
};
</script>
</body>
</html>
代碼解析
-
let ws = new WebSocket("ws://localhost:9527/ws");
:連接 WebSocket 服務器。 -
ws.onmessage = function (event) {...}
:當收到屏幕圖像數據時,創建blob
對象,並更新img
標籤。 -
img.src = URL.createObjectURL(event.data);
:動態顯示截圖。
運行項目效果
我們分別先運行 go 後端代碼,再打開 html 文件,具體效果展示如下圖所示:
⚠️注意:請忽略我運行中出現的錯誤信息,這個是 opencv 的依賴報錯告警,不影響運行,在你的電腦運行的話可能不會出現,只要設置好 opencv 的環境就不會出現了。
前端運行效果圖如下所示:
總結
本方案適用於局域網屏幕共享、遠程桌面監控、在線教學等,如果需要更流暢的視頻流,可以結合 FFmpeg + WebRTC/RTMP 實現更高級的屏幕共享。今天的內容就到此結束了,感謝您的收看,歡迎關注本公衆號!🚀🚀🚀 最後歡迎您的三連!!!🌹🌹🌹
請在微信客戶端打開
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/G8-alfUG8Vo7vdRCOUQgyg