Go語言利用原生庫實現(xiàn)屏幕截取和實時推流功能
本文介紹如何使用 Golang 原生庫 實現(xiàn)一個高效的屏幕實時截圖推送服務。不同于以往依賴 FFmpeg 的方案,我們通過 github.com/kbinani/screenshot 直接捕獲屏幕畫面,并將圖像以 JPEG 格式通過 HTTP 推送給前端瀏覽器播放。

核心功能
- 屏幕截?。菏褂肎o捕獲當前屏幕內(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. 截屏服務模塊 (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)
// 啟動截屏服務
go startCaptureService()
// 設置路由
http.HandleFunc("/stream", streamHandler)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
// 啟動服務器
log.Println("服務啟動: http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
三、Web前端實現(xiàn)
創(chuàng)建一個簡單的index.html文件,前端直接用 image 標簽進行顯示即可:
<!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
五、技術要點說明
使用screenshot庫捕獲屏幕內(nèi)容
采用MJPEG(Motion-JPEG)格式推送視頻流
前端通過簡單的<img>標簽即可播放視頻流
自動重連機制確保網(wǎng)絡不穩(wěn)定時的觀看體驗
到此這篇關于Go語言利用原生庫實現(xiàn)屏幕截取和實時推流功能的文章就介紹到這了,更多相關Go屏幕截取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Golang實現(xiàn)協(xié)程超時控制的方式總結(jié)
我們知道,go協(xié)程如果不做好處理,很容易造成內(nèi)存泄漏,所以對goroutine做超時控制,才能有效避免這種情況發(fā)生,本文為大家整理了兩個常見的Golang超時控制方法,需要的可以收藏一下2023-05-05
使用IDEA配置GO語言的開發(fā)環(huán)境備忘錄
最近在配置idea開發(fā)go語言時碰到很多問題,想著很多人都可能會遇到,所以下面這篇文章主要給大家介紹了關于使用IDEA配置GO語言的開發(fā)環(huán)境,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2024-05-05

