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

 更新时间:2025年06月03日 10:21:06   作者:GetcharZp  
这篇文章主要为大家详细介绍了Go语言利用原生库实现一个高效的屏幕实时截图推送服务,文中的示例代码讲解详细,有需要的小伙伴可以了解下

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

核心功能

  • 屏幕截取:使用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.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")

	// 发送初始帧分隔符
	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: 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空转
		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.Fatal(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="视频流">
    
    <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屏幕截取内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言单控制器和多控制器使用详解

    Go语言单控制器和多控制器使用详解

    这篇文章主要为大家详细介绍了Go语言单控制器和多控制器的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Go语言中的os.Truncate函数用法解读

    Go语言中的os.Truncate函数用法解读

    这篇文章主要介绍了Go语言中的os.Truncate函数用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • Golang实现协程超时控制的方式总结

    Golang实现协程超时控制的方式总结

    我们知道,go协程如果不做好处理,很容易造成内存泄漏,所以对goroutine做超时控制,才能有效避免这种情况发生,本文为大家整理了两个常见的Golang超时控制方法,需要的可以收藏一下
    2023-05-05
  • 一文带你探索Go语言中crypto/md5标准库的强大功能

    一文带你探索Go语言中crypto/md5标准库的强大功能

    我们将从MD5算法的基础知识入手,逐步深入到如何在Go中有效使用crypto/md5标准库,包括基本的使用方法、实际应用案例分析,以及性能和安全性的考量,需要的可以参考下
    2024-02-02
  • golang中的nil接收器详解

    golang中的nil接收器详解

    这篇文章主要介绍了golang中的nil接收器,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • Go中的动态速率限制有效控制流量

    Go中的动态速率限制有效控制流量

    这篇文章主要为大家介绍了Go中的动态速率限制有效控制流量,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Go作用域的理解

    Go作用域的理解

    在Go语言中,作用域是指变量的可见性范围,它定义了变量在程序中的生命周期和可访问性,本文主要介绍了Go作用域的理解,包括局部作用域、全局作用域、命名空间作用域等,感兴趣的可以了解一下
    2023-11-11
  • Go语言编译环境设置教程

    Go语言编译环境设置教程

    Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效率
    2025-07-07
  • Golang设计模式中抽象工厂模式详细讲解

    Golang设计模式中抽象工厂模式详细讲解

    抽象工厂模式用于生成产品族的工厂,所生成的对象是有关联的。如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。比如本例子中使用RDB和XML存储订单信息,抽象工厂分别能生成相关的主订单信息和订单详情信息
    2023-01-01
  • 使用IDEA配置GO语言的开发环境备忘录

    使用IDEA配置GO语言的开发环境备忘录

    最近在配置idea开发go语言时碰到很多问题,想着很多人都可能会遇到,所以下面这篇文章主要给大家介绍了关于使用IDEA配置GO语言的开发环境,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-05-05

最新评论