Go語言利用原生庫實現(xiàn)屏幕截取和實時推流功能
本文介紹如何使用 Golang 原生庫 實現(xiàn)一個高效的屏幕實時截圖推送服務(wù)。不同于以往依賴 FFmpeg 的方案,我們通過 github.com/kbinani/screenshot
直接捕獲屏幕畫面,并將圖像以 JPEG 格式通過 HTTP 推送給前端瀏覽器播放。
核心功能
- 屏幕截?。菏褂肎o捕獲當(dāng)前屏幕內(nèi)容
- 實時推流:將視頻流通過HTTP協(xié)議推送
- Web播放:簡單HTML頁面驗證流媒體
Go后端實現(xiàn)
1. 全局幀緩存模塊 (frame_cache.go)
package main import ( "sync" "time" ) var ( frameCache []byte frameCacheTime time.Time cacheMutex sync.RWMutex ) // 更新幀緩存 func updateFrameCache(frame []byte) { cacheMutex.Lock() defer cacheMutex.Unlock() frameCache = frame frameCacheTime = time.Now() } // 獲取幀緩存 func getFrameCache() ([]byte, time.Time) { cacheMutex.RLock() defer cacheMutex.RUnlock() return frameCache, frameCacheTime }
2. 截屏服務(wù)模塊 (capture_service.go)
package main import ( "bytes" "image/jpeg" "log" "time" "github.com/kbinani/screenshot" ) func startCaptureService() { ticker := time.NewTicker(time.Second / time.Duration(frameRate)) defer ticker.Stop() for range ticker.C { img, err := screenshot.CaptureRect(screenBounds) if err != nil { log.Printf("截屏失敗: %v", err) continue } buf := new(bytes.Buffer) if err := jpeg.Encode(buf, img, &jpeg.Options{Quality: quality}); err != nil { log.Printf("JPEG編碼失敗: %v", err) continue } updateFrameCache(buf.Bytes()) } }
3. 流處理模塊 (stream_handler.go)
package main import ( "fmt" "net/http" "time" ) func streamHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "multipart/x-mixed-replace; boundary=frame") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") // 發(fā)送初始幀分隔符 if _, err := w.Write([]byte("--frame\r\n")); err != nil { return } lastSent := time.Now() for { frame, frameTime := getFrameCache() // 只發(fā)送新幀 if frameTime.After(lastSent) { if _, err := fmt.Fprintf(w, "Content-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n", len(frame)); err != nil { return } if _, err := w.Write(frame); err != nil { return } if _, err := w.Write([]byte("\r\n--frame\r\n")); err != nil { return } if f, ok := w.(http.Flusher); ok { f.Flush() } lastSent = frameTime } // 防止CPU空轉(zhuǎn) time.Sleep(time.Second / time.Duration(frameRate*2)) select { case <-r.Context().Done(): return default: } } }
4. 主程序模塊 (main.go)
package main import ( "image" "log" "net/http" "github.com/kbinani/screenshot" ) var ( quality = 50 // JPEG質(zhì)量(1-100) frameRate = 10 // 幀率(FPS) screenBounds = image.Rect(0, 0, 0, 0) // 屏幕尺寸 ) func main() { // 初始化截屏區(qū)域 if n := screenshot.NumActiveDisplays(); n <= 0 { log.Fatal("未檢測到活動顯示器") } screenBounds = screenshot.GetDisplayBounds(0) // 啟動截屏服務(wù) go startCaptureService() // 設(shè)置路由 http.HandleFunc("/stream", streamHandler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "index.html") }) // 啟動服務(wù)器 log.Println("服務(wù)啟動: http://localhost:8080") log.Fatal(http.ListenAndServe(":8080", nil)) }
三、Web前端實現(xiàn)
創(chuàng)建一個簡單的index.html
文件,前端直接用 image 標(biāo)簽進(jìn)行顯示即可:
<!DOCTYPE html> <html> <head> <title>Go屏幕流測試</title> <style> body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; } #video { max-width: 90%; border: 1px solid #ccc; margin: 20px auto; } </style> </head> <body> <h1>Go屏幕流測試播放器</h1> <img id="video" src="/stream" alt="視頻流"> <div> <button onclick="window.location.reload()">重新加載</button> </div> <script> // 自動重連邏輯 const video = document.getElementById('video'); video.onerror = function() { setTimeout(function() { video.src = '/stream?t=' + new Date().getTime(); }, 1000); }; </script> </body> </html>
四、運行步驟
1.安裝依賴庫:
go get github.com/kbinani/screenshot
2.運行Go程序:
go run main.go
3.打開瀏覽器訪問: http://localhost:8080
五、技術(shù)要點說明
使用screenshot
庫捕獲屏幕內(nèi)容
采用MJPEG(Motion-JPEG)格式推送視頻流
前端通過簡單的<img>
標(biāo)簽即可播放視頻流
自動重連機制確保網(wǎng)絡(luò)不穩(wěn)定時的觀看體驗
到此這篇關(guān)于Go語言利用原生庫實現(xiàn)屏幕截取和實時推流功能的文章就介紹到這了,更多相關(guān)Go屏幕截取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang?throttled基于GCRA速率限制庫使用探索
這篇文章主要為大家介紹了Golang?throttled基于GCRA速率限制庫使用實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01golang創(chuàng)建文件目錄os.Mkdir,os.MkdirAll的區(qū)別說明
本文主要講述os.Mkdir、os.MkdirAll區(qū)別以及在創(chuàng)建文件目錄過程中的一些其他技巧,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03Go 語言json.Unmarshal 遇到的小問題(推薦)
這篇文章主要介紹了 Go 語言json.Unmarshal 遇到的小問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07golang bad file descriptor問題的解決方法
這篇文章主要給大家介紹了golang bad file descriptor問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02