使用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 回复
以下代码展示了如何将视频捕获并实时流传输到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传输的不同实现方式,可以根据服务器端的接收需求选择合适的方法。


