📌

プログラムから4K画質webカメラの静止画を最高画質で保存する

2021/02/22に公開

4K画質のwebカメラを最高画質で画像保存する方法を検討します。はじめにJavaScriptのAPI(getUserMedia)で拾うことを試してみましたがうまくいきませんでした(macOSとwindowsで送れる解像度に差がありました。CPUやGPUも当然違うので、OSというよりこちらに影響している可能性があります)。次にOBSのスクリーンショット機能を試してみると、最高画質で保存出来きることが分かりました(webカメラに依ると思います。今回使ったカメラは公式にOBSで動作すると書かれています)。OBSはobs-websocketを使うと遠隔操作できるらしいので、これを利用してスクリーンショットを撮る方法を調べてみました(OBSのバージョンはmacOSは26.1.2、windowsは26.1.1)。結論としては、この方法でうまくいきました。

4K画質で保存できることを確認したwebカメラはLogicoolのC1000eRで使用したOSはwindowsです。細かいことを言うと、4K画質を扱うにはWebカメラのファームウェアのバージョンを上げる必要があります。ファームウェアアップデートプログラムはここを開いて、Brio Firmware Upgradeのところからダウンロードできます。

Brioの公式ソフトウェアのダウンロードページ

4K画質を扱うための、さらに細かい条件については公式のこちらのページに書かれています。

手元にmacしか無いので、この記事の画像キャプチャはmacのものを使用しますが、プログラムはどちらでも動きます(4Kで静止画が撮れるのを確認しているのはwindowsのみです)。

まずOBSをプログラムから制御するためにobs-websocketをインストールします。インストーラーはここからダウンロード出来ます。インストール後にOBSを再起動すると、Websocketサーバーの設定について聞かれます。その後もツールに"Websocketサーバー設定"が追加されているので、設定を変更ときはここを選択します。

設定内容は次のようになっています。今回は外部に公開して使用するわけではないので、認証はオフにしておきます。また、接続を維持するわけでもないときは、切断のたびに通知が飛ぶのでオフにしたほうが良いと思います。

この状態でプログラムからシーンの画像を静止画として保存します。シーン名は画像のようにsceneとします。

ソースのwebcamは映像キャプチャデバイスを選んで、内蔵カメラを選択します(外部webカメラの場合はデバイスの選択を変更。プリセットも4K画質を選ぶ)。

設定を開いて、映像を選択して基本解像度、出力解像度をともにプリセットに合わせます(この項目は選択式のように見えますが、選択肢にない画質については直接入力して下さい)。

設定を適用後、次のプログラムをコンパイルして実行します。

main.go
package main

import (
	"fmt"
	"log"
	"os"
	"path"
	"time"

	obsws "github.com/christopher-dG/go-obs-websocket"
)

func main() {
	c := obsws.Client{Host: "localhost", Port: 4444}
	if err := c.Connect(); err != nil {
		log.Fatal(err)
	}
	defer c.Disconnect()
	obsws.SetReceiveTimeout(time.Second * 2)
	exePath, _ := os.Executable()
	baseDir := path.Join(path.Dir(exePath), "images")
	_, err := os.Stat(baseDir)
	if os.IsNotExist(err) {
		os.Mkdir(baseDir, 0777)
	}
	imagePath := path.Join(baseDir, fmt.Sprintf("%s.png", time.Now().Format("20060102150405")))
	resp := obsws.NewTakeSourceScreenshotRequest("scene", "png", imagePath, 1280, 720)
	err = resp.Send(c)
	if err != nil {
		log.Fatal(err)
	}
}

pngjpgしか確認していませんが、windowsの場合はjpgにすると静止画は保存されませんでした。

Discussion