开发者

Go语言利用原生库实现屏幕截取和实时推流功能

目录
  • 核心功能
  • Go后端实现
    • 1. 全局帧缓存模块 (frame_cache.编程go)
    • 2. 截屏服务模块 (capture_service.go)
    • 3. 流处理模块 (stream_handler.go)
    • 4. 主程序模块 (main.go)
  • 三、Web前端实现
    • 四、运行步骤
      • 五、技术要点说明

        本文介绍如何使用 golang 原生库 实现一个高效的屏幕实时截图推送服务。不同于以往依赖 FFmpeg 的方案,我们通过 github.com/kbinani/screenshot 直接捕获屏幕画面,并将图像以 JPEG 格式通过 HTTP 推送给前端浏览器播放。

        Go语言利用原生库实现屏幕截取和实时推流功能

        核心功能

        • 屏幕截取:使用Go捕获当前屏幕内容
        • 实时推流:将视频流通过HTTP协议推送
        • Web播放:简单html页面验证流媒体

        Go后端实现

        1. 全局帧缓存模块 (frame_cache.go)

        package main
        
        import (
        	"sync"
        	"time"
        )
        
        var (
        	frameCache     []byte
        	frameCacheTime time.Time
        	cacheMutex     sync.RWMutex
        )
        
        // 更新帧缓存
        func updateFrameCache(frame []byte) {
        	cacheMutex.Lockjavascript()
        	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")
        
        	// 发送初始帧分隔符
        	if _, err := w.Write([]byte("--frame\r\n")); err != nil {
        		return
        	}
        
        	lastSent := time.Now()
        	for {
        		frame, frameTime := getFrameCache()
        
        		// 只发送新帧
        		if frameTime.After(lastSent) {
        			if _, err := fmt.Fprintf(w,
        				"Content-Type: ima编程客栈ge/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空转
        		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质量(1-100)
        	frameRate    = 10                     // 帧率(FPS)
        	screenBounds = image.Rect(0, 0, 0, 0) // 屏幕尺寸
        )
        
        func main() {
        	// 初始化截屏区域
        	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.Fat编程al(http.ListenAndServe(":8080", nil))
        }
        

        三、Web前端实现

        创建一个简单的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="Go语言利用原生库实现屏幕截取和实时推流功能">
            
            <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库捕获屏幕内容

        采用MJPEG(Motion-JPEG)格式推送视频流

        前端通过简单的<img>标签即可播放视频流

        自动重连机制确保网络不稳定时的观看体验

        到此这篇关于Go语言利用原生库实现屏幕截取和实时推流功能的文章就介绍到这了,更多相关Go屏幕截取内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜