使用Golang实现视频捕获并实时流传输到Web的方法

使用Golang实现视频捕获并实时流传输到Web的方法 以下代码可以读取摄像头并在GUI窗口中显示,我想将同样的内容推送到我的服务器地址 localhost:8080/cam,该如何实现?

package main

import (
	"gocv.io/x/gocv"
)

func main() {
	webcam, _ := gocv.VideoCaptureDevice(0)
	defer webcam.Close() // 执行完成后关闭摄像头
	window := gocv.NewWindow("Hello")
	defer window.Close() // 执行完成后关闭GUI窗口(虽然会自动完成)
	img := gocv.NewMat()
	defer img.Close() // 执行完成后关闭图像

	for {
		webcam.Read(&img)
		window.IMShow(img)
        // 希望在此处将视频流推送到 localhost:8080/cam
		if window.WaitKey(1) == 27 { // 27 => Esc
			break
		}
	}
}

更多关于使用Golang实现视频捕获并实时流传输到Web的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

同一个项目还有一个 https://github.com/hybridgroup/mjpeg 项目和 https://github.com/hybridgroup/gocv/tree/release/cmd/mjpeg-streamer,它们演示了如何创建 MJPEG 流。

更多关于使用Golang实现视频捕获并实时流传输到Web的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下代码展示了如何将视频捕获并实时流传输到Web服务器。这里使用HTTP POST请求将每一帧图像以JPEG格式推送到指定的服务器端点。

package main

import (
    "bytes"
    "gocv.io/x/gocv"
    "image/jpeg"
    "net/http"
    "time"
)

func main() {
    webcam, _ := gocv.VideoCaptureDevice(0)
    defer webcam.Close()
    window := gocv.NewWindow("Hello")
    defer window.Close()
    img := gocv.NewMat()
    defer img.Close()

    // 设置HTTP客户端,配置超时时间
    client := &http.Client{
        Timeout: 5 * time.Second,
    }

    for {
        if ok := webcam.Read(&img); !ok || img.Empty() {
            continue
        }

        // 显示在本地窗口
        window.IMShow(img)

        // 将Mat转换为JPEG字节流
        buf := new(bytes.Buffer)
        imgBytes, _ := gocv.IMEncode(".jpg", img)
        jpeg.Encode(buf, imgBytes, nil)
        imgBytes.Close()

        // 创建HTTP POST请求
        req, _ := http.NewRequest("POST", "http://localhost:8080/cam", buf)
        req.Header.Set("Content-Type", "image/jpeg")

        // 异步发送请求避免阻塞主循环
        go func() {
            resp, err := client.Do(req)
            if err == nil {
                defer resp.Body.Close()
            }
        }()

        if window.WaitKey(1) == 27 {
            break
        }
    }
}

如果服务器端需要处理MJPEG流,可以使用以下改进版本,通过multipart流实现持续传输:

package main

import (
    "bytes"
    "gocv.io/x/gocv"
    "image/jpeg"
    "mime/multipart"
    "net/http"
    "time"
)

func main() {
    webcam, _ := gocv.VideoCaptureDevice(0)
    defer webcam.Close()
    window := gocv.NewWindow("Hello")
    defer window.Close()
    img := gocv.NewMat()
    defer img.Close()

    client := &http.Client{
        Timeout: 30 * time.Second, // 长超时用于流传输
    }

    for {
        if ok := webcam.Read(&img); !ok || img.Empty() {
            continue
        }

        window.IMShow(img)

        // 创建multipart写入器
        body := &bytes.Buffer{}
        writer := multipart.NewWriter(body)
        part, _ := writer.CreateFormFile("frame", "frame.jpg")

        // 编码图像
        imgBytes, _ := gocv.IMEncode(".jpg", img)
        jpeg.Encode(part, imgBytes, &jpeg.Options{Quality: 80})
        imgBytes.Close()
        writer.Close()

        // 发送请求
        req, _ := http.NewRequest("POST", "http://localhost:8080/cam", body)
        req.Header.Set("Content-Type", writer.FormDataContentType())

        go func() {
            resp, err := client.Do(req)
            if err == nil {
                defer resp.Body.Close()
            }
        }()

        if window.WaitKey(1) == 27 {
            break
        }
    }
}

对于需要低延迟的场景,可以考虑使用WebSocket协议传输。以下是使用gorilla/websocket库的示例:

package main

import (
    "bytes"
    "gocv.io/x/gocv"
    "image/jpeg"
    "net/url"
    "time"

    "github.com/gorilla/websocket"
)

func main() {
    webcam, _ := gocv.VideoCaptureDevice(0)
    defer webcam.Close()
    window := gocv.NewWindow("Hello")
    defer window.Close()
    img := gocv.NewMat()
    defer img.Close()

    // 建立WebSocket连接
    u := url.URL{Scheme: "ws", Host: "localhost:8080", Path: "/cam"}
    conn, _, _ := websocket.DefaultDialer.Dial(u.String(), nil)
    defer conn.Close()

    for {
        if ok := webcam.Read(&img); !ok || img.Empty() {
            continue
        }

        window.IMShow(img)

        // 编码图像
        buf := new(bytes.Buffer)
        imgBytes, _ := gocv.IMEncode(".jpg", img)
        jpeg.Encode(buf, imgBytes, &jpeg.Options{Quality: 75})
        imgBytes.Close()

        // 通过WebSocket发送
        go func(data []byte) {
            conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
            conn.WriteMessage(websocket.BinaryMessage, data)
        }(buf.Bytes())

        if window.WaitKey(1) == 27 {
            break
        }
    }
}

这些示例提供了从基本的HTTP POST到更高效的WebSocket传输的不同实现方式,可以根据服务器端的接收需求选择合适的方法。

回到顶部