使用Golang获取笔记本电脑或系统摄像头的视频流

使用Golang获取笔记本电脑或系统摄像头的视频流 我想使用Go语言创建一个命令行界面工具。

该Go语言CLI工具应能够列出连接到笔记本电脑或系统的摄像头和麦克风设备,从系统或笔记本电脑获取视频画面或视频流,将视频流写入本地系统的文件,以及将视频流传输到服务器,以便在打开该门户网站时能够看到视频。

目标系统:

  1. Linux
  2. Windows
  3. macOS

功能需求:

  1. 列出已连接的摄像头和麦克风
  2. 从选定的摄像头获取视频流
  3. 获取图像
  4. 存储来自摄像头的视频流,以便可以在媒体播放器中作为视频播放
  5. 将视频流发送到服务器,以便可以在其他设备上访问(来自安全摄像头的实时流) 注意:我不想在浏览器中创建访问摄像头的功能

问题:

  1. 是否有任何Go语言的库/包可以帮助我实现上述列出的功能?

更多关于使用Golang获取笔记本电脑或系统摄像头的视频流的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于使用Golang获取笔记本电脑或系统摄像头的视频流的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


对于跨平台的摄像头视频流处理,Go语言有几个优秀的库可以选择。以下是针对您需求的解决方案:

推荐库

1. gocv (OpenCV Go绑定)

package main

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

func main() {
    // 列出可用摄像头
    for i := 0; i < 10; i++ {
        webcam, err := gocv.OpenVideoCapture(i)
        if err != nil {
            continue
        }
        defer webcam.Close()
        fmt.Printf("摄像头 %d 可用\n", i)
    }

    // 打开默认摄像头
    webcam, err := gocv.OpenVideoCapture(0)
    if err != nil {
        log.Fatal("无法打开摄像头:", err)
    }
    defer webcam.Close()

    // 创建窗口
    window := gocv.NewWindow("摄像头流")
    defer window.Close()

    img := gocv.NewMat()
    defer img.Close()

    // 捕获视频流
    for {
        if ok := webcam.Read(&img); !ok || img.Empty() {
            log.Print("无法读取帧")
            continue
        }

        window.IMShow(img)
        if window.WaitKey(1) >= 0 {
            break
        }
    }
}

2. pion/mediadevices (WebRTC媒体设备)

package main

import (
    "context"
    "fmt"
    "log"
    "github.com/pion/mediadevices"
    "github.com/pion/mediadevices/pkg/prop"
    _ "github.com/pion/mediadevices/pkg/driver/camera" // 注册摄像头驱动
    _ "github.com/pion/mediadevices/pkg/driver/microphone" // 注册麦克风驱动
)

func main() {
    // 列出所有媒体设备
    devices := mediadevices.EnumerateDevices()
    for _, device := range devices {
        fmt.Printf("设备: %s, 类型: %s\n", device.Label, device.Kind)
    }

    // 获取视频流
    mediaStream, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
        Video: func(constraint *mediadevices.MediaTrackConstraints) {
            constraint.Width = prop.Int(640)
            constraint.Height = prop.Int(480)
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    // 获取视频轨道
    tracks := mediaStream.GetVideoTracks()
    for _, track := range tracks {
        fmt.Printf("视频轨道: %s\n", track.ID())
    }
}

完整示例:视频捕获和保存

package main

import (
    "fmt"
    "log"
    "os"
    "gocv.io/x/gocv"
    "github.com/pion/webrtc/v3"
    "github.com/pion/webrtc/v3/pkg/media"
    "github.com/pion/webrtc/v3/pkg/media/ivfwriter"
)

// 1. 列出摄像头设备
func listCameras() {
    fmt.Println("可用摄像头:")
    for i := 0; i < 10; i++ {
        webcam, err := gocv.OpenVideoCapture(i)
        if err != nil {
            continue
        }
        webcam.Close()
        fmt.Printf("  摄像头 %d\n", i)
    }
}

// 2. 捕获视频并保存到文件
func captureAndSave(filename string, cameraID int) {
    webcam, err := gocv.OpenVideoCapture(cameraID)
    if err != nil {
        log.Fatal(err)
    }
    defer webcam.Close()

    // 设置视频参数
    webcam.Set(gocv.VideoCaptureFrameWidth, 640)
    webcam.Set(gocv.VideoCaptureFrameHeight, 480)
    webcam.Set(gocv.VideoCaptureFPS, 30)

    // 创建视频写入器
    writer, err := gocv.VideoWriterFile(
        filename,
        "MJPG",
        30,
        640, 480, true)
    if err != nil {
        log.Fatal(err)
    }
    defer writer.Close()

    img := gocv.NewMat()
    defer img.Close()

    fmt.Printf("正在录制到 %s...\n", filename)
    for i := 0; i < 300; i++ { // 录制10秒(30fps * 10)
        if ok := webcam.Read(&img); !ok {
            break
        }
        writer.Write(img)
    }
    fmt.Println("录制完成")
}

// 3. 流式传输到服务器
func streamToServer(cameraID int, serverURL string) {
    // 使用WebRTC进行流式传输
    config := webrtc.Configuration{
        ICEServers: []webrtc.ICEServer{
            {URLs: []string{"stun:stun.l.google.com:19302"}},
        },
    }

    peerConnection, err := webrtc.NewPeerConnection(config)
    if err != nil {
        log.Fatal(err)
    }

    // 添加视频轨道
    videoTrack, err := webrtc.NewTrackLocalStaticSample(
        webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8},
        "video",
        "camera",
    )
    if err != nil {
        log.Fatal(err)
    }

    _, err = peerConnection.AddTrack(videoTrack)
    if err != nil {
        log.Fatal(err)
    }

    // 捕获摄像头帧并发送
    go func() {
        webcam, _ := gocv.OpenVideoCapture(cameraID)
        defer webcam.Close()

        img := gocv.NewMat()
        defer img.Close()

        for {
            webcam.Read(&img)
            // 这里需要将gocv.Mat转换为视频帧并发送
            // 实际实现需要编码处理
        }
    }()

    // 创建offer并连接到服务器
    offer, err := peerConnection.CreateOffer(nil)
    if err != nil {
        log.Fatal(err)
    }

    err = peerConnection.SetLocalDescription(offer)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("连接到服务器: %s\n", serverURL)
}

安装依赖

# 安装gocv
go get -u gocv.io/x/gocv

# 安装pion相关库
go get github.com/pion/mediadevices
go get github.com/pion/webrtc/v3

# 根据平台安装OpenCV依赖
# Ubuntu/Debian
sudo apt-get install libopencv-dev

# macOS
brew install opencv

# Windows
# 从 https://opencv.org/releases/ 下载并设置环境变量

构建命令行工具

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    listCmd := flag.NewFlagSet("list", flag.ExitOnError)
    recordCmd := flag.NewFlagSet("record", flag.ExitOnError)
    streamCmd := flag.NewFlagSet("stream", flag.ExitOnError)

    if len(os.Args) < 2 {
        fmt.Println("用法: camtool <command> [options]")
        fmt.Println("命令:")
        fmt.Println("  list    列出摄像头设备")
        fmt.Println("  record  录制视频")
        fmt.Println("  stream  流式传输到服务器")
        os.Exit(1)
    }

    switch os.Args[1] {
    case "list":
        listCmd.Parse(os.Args[2:])
        listCameras()
    case "record":
        filename := recordCmd.String("output", "output.avi", "输出文件名")
        cameraID := recordCmd.Int("camera", 0, "摄像头ID")
        recordCmd.Parse(os.Args[2:])
        captureAndSave(*filename, *cameraID)
    case "stream":
        url := streamCmd.String("server", "", "服务器URL")
        cameraID := streamCmd.Int("camera", 0, "摄像头ID")
        streamCmd.Parse(os.Args[2:])
        streamToServer(*cameraID, *url)
    default:
        fmt.Println("未知命令:", os.Args[1])
        os.Exit(1)
    }
}

这个解决方案使用gocv进行视频捕获和处理,使用pion/webrtc进行流式传输,可以满足您的所有功能需求。

回到顶部