はじめに
OpenGoProのAPIがわかりにくく、詳細がよくわからないので、試しながら調べた際のメモ。やりたかったのはUSB接続したGoPro Hero12に対して、以下のような設定で撮影して、ファイルを取得すること。
- ナイトフォト
- RAW撮影
- ISO最大: 100
- シャープネス: 低
環境
- GoPro Hero12 (USB接続)
- macOS 14.5(23F79)
- Python 3.11.5
- open_gopro ver.0.16.2
準備
MacBookProとUSB Type-CでGoPro Hero12を接続。
GoProのバッテリを取り外し、USBから電源供給すると連続稼働できる。バッテリをつけていると供給電力より消費電力が多く、バッテリが減って電源が落ちる。
pip install open_gopro rawpy opencv-python
接続+カメラ情報取得
カメラのシリアル番号の末尾が"789"の場合はgopro = WiredGoPro(serial="789")
のように指定する。接続するのが1台の場合は何も指定しなくてよい。GoProはUSBのNetwork Control Model (NCM)を利用しており、Ethernet接続しているかのようにGoProにアクセスできる。その際のGoProのIPアドレスは、172.2X.1YZ.51:8080のように決定され、ここでXYZはシリアル番号の末尾3桁である。シリアル番号がC0000123456789のときは、IPアドレスは172.27.189.51となる。詳細はこちら。
from open_gopro import WiredGoPro, Params, constants
import asyncio
import os
useGoPro12=True
gopro = WiredGoPro()
await gopro.open()
while not await gopro.is_ready:
pass
if useGoPro12: # 現状、GoPro Hero12のget_camera_info()を使えない様子。
cameraInfo = await gopro.http_command.get_camera_info()
print(cameraInfo)
出力
{
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/info",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
"data" : {
"model_number" : "62",
"model_name" : "HERO12 Black",
"firmware_version" : "H23.01.01.30.70",
"serial_number" : "C0000123456XYZ",
"ap_mac_addr" : "0xxxxxxxxxxx",
"ap_ssid" : "GP12345678",
},
}
カメラの状態を確認
現在のカメラの設定、状態を取得する。
state = await gopro.http_command.get_camera_state()
print(state)
出力
{
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/state",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
"data" : {
"StatusId.BATT_PRESENT" : "True",
"StatusId.BATT_LEVEL" : "4",
"StatusId.DEPRECATED_3" : "DEPRECATED",
"StatusId.DEPRECATED_4" : "DEPRECATED",
"StatusId.SYSTEM_HOT" : "False",
"StatusId.SYSTEM_BUSY" : "False",
"StatusId.QUICK_CAPTURE" : "False",
"StatusId.ENCODING" : "False",
"StatusId.LCD_LOCK_ACTIVE" : "False",
"StatusId.VIDEO_PROGRESS" : "0",
"StatusId.INTERNAL_14" : "0",
"StatusId.WIRELESS_ENABLED" : "True",
"StatusId.PAIR_STATE" : "PairState.NOT_STARTED",
"StatusId.PAIR_TYPE" : "PairType.NOT_PAIRING",
"StatusId.WAP_SCAN_STATE" : "WAPState.NEVER_STARTED",
"StatusId.WAP_SCAN_TIME" : "0",
"StatusId.WAP_PROV_STAT" : "WAPState.NEVER_STARTED",
"StatusId.REMOTE_CTRL_CONN" : "False",
"StatusId.WLAN_SSID" : "",
"StatusId.AP_SSID" : "GP24863282",
"StatusId.APP_COUNT" : "0",
"StatusId.PREVIEW_ENABLED" : "False",
"StatusId.SD_STATUS" : "SDStatus.OK",
"StatusId.PHOTOS_REM" : "1408",
"StatusId.VIDEO_REM" : "4306",
"StatusId.NUM_TOTAL_PHOTO" : "4",
"StatusId.NUM_TOTAL_VIDEO" : "1",
"StatusId.OTA_STAT" : "OTAStatus.IDLE",
"StatusId.DOWNLOAD_CANCEL_PEND" : "False",
"StatusId.LOCATE_ACTIVE" : "False",
"StatusId.MULTI_COUNT_DOWN" : "0",
"StatusId.SPACE_REM" : "62093524",
"StatusId.STREAMING_SUPP" : "True",
"StatusId.WIFI_BARS" : "4",
"StatusId.NUM_HILIGHTS" : "0",
"StatusId.LAST_HILIGHT" : "0",
"StatusId.NEXT_POLL" : "500",
"StatusId.ANALYTICS_RDY" : "AnalyticsState.ON_CONNECT",
"StatusId.TIMELAPSE_REM" : "0",
"StatusId.EXPOSURE_TYPE" : "ExposureMode.DISABLED",
"StatusId.EXPOSURE_X" : "100",
"StatusId.EXPOSURE_Y" : "100",
"StatusId.GPS_STAT" : "False",
"StatusId.AP_STATE" : "False",
"StatusId.INT_BATT_PER" : "100",
"StatusId.ACC_MIC_STAT" : "ExposureMode.DISABLED",
"StatusId.DIGITAL_ZOOM" : "0",
"StatusId.WIRELESS_BAND" : "WifiBand.BAND_5_GHZ",
"StatusId.DIG_ZOOM_ACTIVE" : "False",
"StatusId.MOBILE_VIDEO" : "False",
"StatusId.BAND_5GHZ_AVAIL" : "False",
"StatusId.SYSTEM_READY" : "True",
"StatusId.BATT_OK_OTA" : "True",
"StatusId.VIDEO_LOW_TEMP" : "False",
"StatusId.ORIENTATION" : "Orientation.UPRIGHT",
"StatusId.ZOOM_ENCODING" : "False",
"StatusId.FLATMODE_ID" : "Flatmode.NIGHT_PHOTO",
"StatusId.INTERNAL_90" : "0",
"StatusId.LOGS_READY" : "False",
"StatusId.VIDEO_PRESETS" : "6",
"StatusId.PHOTO_PRESETS" : "65539",
"StatusId.TIMELAPSE_PRESETS" : "131072",
"StatusId.PRESETS_GROUP" : "1001",
"StatusId.ACTIVE_PRESET" : "65539",
"StatusId.PRESET_MODIFIED" : "0",
"StatusId.CAPT_DELAY_ACTIVE" : "False",
"StatusId.MEDIA_MOD_MIC_STAT" : "MediaModMicStatus.REMOVED",
"StatusId.TIMEWARP_SPEED_RAMP" : "TimeWarpSpeed.SPEED_15X",
"StatusId.CAMERA_LENS_TYPE" : "MaxLensMode.DEFAULT",
"StatusId.VIDEO_HINDSIGHT" : "False",
"StatusId.SCHEDULED_PRESET" : "4294967295",
"StatusId.SCHEDULED_CAPTURE" : "False",
"StatusId.CREATING_PRESET" : "False",
"StatusId.MEDIA_MOD_STAT" : "MediaModStatus.SELFIE_0_HDMI_0_MEDIAMODCONNECTED_FALSE",
"StatusId.SD_RATING_CHECK_ERROR" : "False",
"StatusId.SD_WRITE_SPEED_ERROR" : "0",
"StatusId.TURBO_MODE" : "False",
"StatusId.CAMERA_CONTROL" : "CameraControl.IDLE",
"StatusId.USB_CONNECTED" : "False",
"StatusId.CONTROL_OVER_USB" : "True",
"StatusId.TOTAL_SD_SPACE_KB" : "62205722",
"SettingId.RESOLUTION" : "Resolution.RES_4K_16_9",
"SettingId.FPS" : "FPS.FPS_240",
"SettingId.INTERNAL_5" : "0",
"SettingId.INTERNAL_6" : "0",
"SettingId.INTERNAL_13" : "0",
"SettingId.INTERNAL_19" : "0",
"SettingId.INTERNAL_24" : "3",
"SettingId.INTERNAL_30" : "110",
"SettingId.INTERNAL_31" : "0",
"SettingId.INTERNAL_32" : "10",
"SettingId.INTERNAL_37" : "0",
"SettingId.INTERNAL_41" : "9",
"SettingId.INTERNAL_42" : "8",
"SettingId.INTERNAL_43" : "0",
"SettingId.INTERNAL_44" : "9",
"SettingId.INTERNAL_45" : "8",
"SettingId.INTERNAL_47" : "7",
"SettingId.INTERNAL_54" : "1",
"SettingId.AUTO_OFF" : "AutoOff.MIN_5",
"SettingId.INTERNAL_62" : "1200000",
"SettingId.INTERNAL_64" : "4",
"SettingId.INTERNAL_75" : "3",
"SettingId.INTERNAL_76" : "0",
"SettingId.INTERNAL_84" : "5",
"SettingId.INTERNAL_85" : "0",
"SettingId.INTERNAL_86" : "0",
"SettingId.INTERNAL_87" : "40",
"SettingId.INTERNAL_88" : "50",
"SettingId.LED" : "LED.ALL_ON",
"SettingId.INTERNAL_102" : "0",
"SettingId.INTERNAL_103" : "3",
"SettingId.INTERNAL_105" : "0",
"SettingId.VIDEO_ASPECT_RATIO" : "VideoAspectRatio.RATIO_4_3",
"SettingId.INTERNAL_111" : "0",
"SettingId.INTERNAL_112" : "255",
"SettingId.INTERNAL_114" : "1",
"SettingId.INTERNAL_115" : "0",
"SettingId.INTERNAL_116" : "2",
"SettingId.INTERNAL_117" : "2",
"SettingId.INTERNAL_118" : "4",
"SettingId.VIDEO_FOV" : "VideoFOV.WIDE",
"SettingId.PHOTO_FOV" : "PhotoFOV.WIDE",
"SettingId.MULTI_SHOT_FOV" : "MultishotFOV.WIDE",
"SettingId.PHOTO_OUTPUT" : "PhotoOutput.RAW",
"SettingId.INTERNAL_126" : "0",
"SettingId.MEDIA_FORMAT" : "MediaFormat.TIME_LAPSE_VIDEO",
"SettingId.INTERNAL_129" : "2",
"SettingId.INTERNAL_130" : "33",
"SettingId.INTERNAL_131" : "20",
"SettingId.INTERNAL_132" : "0",
"SettingId.ANTI_FLICKER" : "AntiFlicker.HZ_50",
"SettingId.HYPERSMOOTH" : "HypersmoothMode.OFF",
"SettingId.INTERNAL_139" : "3",
"SettingId.INTERNAL_144" : "18",
"SettingId.INTERNAL_145" : "0",
"SettingId.INTERNAL_146" : "0",
"SettingId.INTERNAL_147" : "0",
"SettingId.INTERNAL_148" : "0",
"SettingId.INTERNAL_149" : "2",
"SettingId.INTERNAL_153" : "100",
"SettingId.INTERNAL_154" : "2",
"SettingId.INTERNAL_156" : "100",
"SettingId.INTERNAL_157" : "100",
"SettingId.INTERNAL_158" : "1",
"SettingId.INTERNAL_159" : "1",
"SettingId.INTERNAL_160" : "0",
"SettingId.INTERNAL_161" : "100",
"SettingId.INTERNAL_164" : "100",
"SettingId.INTERNAL_165" : "0",
"SettingId.INTERNAL_166" : "0",
"SettingId.HINDSIGHT" : "Hindsight.OFF",
"SettingId.INTERNAL_168" : "0",
"SettingId.INTERNAL_169" : "1",
"SettingId.PHOTO_INTERVAL" : "PhotoInterval.OFF",
"SettingId.PHOTO_INTERVAL_DURATION" : "PhotoDuration.OFF",
"SettingId.CAMERA_UX_MODE" : "CameraUxMode.PRO",
"SettingId.VIDEO_EASY_MODE" : "10",
"SettingId.WIFI_BAND" : "WifiBand.BAND_5_GHZ",
"SettingId.STAR_TRAIL_LENGTH" : "StarTrailLength.MAX",
"SettingId.BIT_RATE" : "BitRate.STANDARD",
"SettingId.BIT_DEPTH" : "BitDepth.BIT_8",
"SettingId.VIDEO_PROFILE" : "VideoProfile.STANDARD",
"SettingId.VIDEO_MODE" : "VideoMode.HIGHEST",
"SettingId.TIMELAPSE_MODE" : "TimelapseMode.TIMEWARP",
"SettingId.ADDON_MAX_LENS_MOD" : "MaxLensModType.NONE",
"SettingId.ADDON_MAX_LENS_MOD_ENABLE" : "Toggle.DISABLE",
"SettingId.PHOTO_MODE" : "PhotoMode.SUPER",
"SettingId.MULTI_SHOT_NLV_ASPECT_RATIO" : "EasyAspectRatio.WIDESCREEN",
"SettingId.FRAMING" : "Framing.WIDESCREEN",
},
}
撮影モード(静止画、動画、タイムラプス)の取得
撮影モード(静止画、動画、タイムラプス)はプリセット/プリセットグループ機能を利用して設定する。
https://gopro.github.io/OpenGoPro/http#tag/Presets/operation/OGP_PRESET_SET_GROUP
プリセットはプリセットグループに分かれて定義され、プリセットグループにはVIDEO_PRESETS
, PHOTO_PRESETS
, TIMELAPSE_PRESETS
がある。ナイトフォトモードはPHOTO_PRESETSプリセットグループの一つとして登録されている。
現在のプリセット(番号)は以下のように取得できるので、この番号をstateから探すと現在のモードがわかる。
active_preset_id = state.data.get(constants.StatusId.ACTIVE_PRESET)
print(f"active_preset_id: {active_preset_id}")
video_preset_id = state.data.get(constants.StatusId.VIDEO_PRESETS)
photo_preset_id = state.data.get(constants.StatusId.PHOTO_PRESETS)
timelapse_preset_id = state.data.get(constants.StatusId.TIMELAPSE_PRESETS)
# 現在のプリセットを取得
if active_preset_id == video_preset_id:
print("VIDEO mode")
elif active_preset_id == photo_preset_id:
print("PHOTO mode")
elif active_preset_id == timelapse_preset_id:
print("TIMELAPSE mode")
else:
print("Unknown mode")
出力
active_preset_id: 65539
PHOTO mode
全てのプリセット情報は以下のように得られる。
preset_status= await gopro.http_command.get_preset_status()
print(preset_status)
出力
{
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/info",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
"data" : {
"presetGroupArray" : [
{
"id" : "PRESET_GROUP_ID_VIDEO",
"presetArray" : [
{
"id" : "6",
"mode" : "FLAT_MODE_VIDEO",
"titleId" : "PRESET_TITLE_CUSTOM",
"userDefined" : "True",
"icon" : "PRESET_ICON_CUSTOM",
"settingArray" : [
{
"id" : "2",
"value" : "105",
"isCaption" : "True",
}, {
"id" : "3",
"value" : "6",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "10",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "0",
"mode" : "FLAT_MODE_VIDEO",
"titleId" : "PRESET_TITLE_VIDEO",
"userDefined" : "False",
"icon" : "PRESET_ICON_VIDEO",
"settingArray" : [
{
"id" : "2",
"value" : "28",
"isCaption" : "True",
}, {
"id" : "3",
"value" : "6",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "True",
}
],
"canAddPreset" : "True",
"icon" : "PRESET_GROUP_VIDEO_ICON_ID",
}, {
"id" : "PRESET_GROUP_ID_PHOTO",
"presetArray" : [
{
"id" : "65542",
"mode" : "FLAT_MODE_PHOTO_NIGHT",
"titleId" : "PRESET_TITLE_CUSTOM",
"userDefined" : "True",
"icon" : "PRESET_ICON_CUSTOM",
"settingArray" : [
{
"id" : "125",
"value" : "1",
"isCaption" : "True",
}, {
"id" : "19",
"value" : "0",
"isCaption" : "True",
}, {
"id" : "122",
"value" : "101",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "65536",
"mode" : "FLAT_MODE_PHOTO_SINGLE",
"titleId" : "PRESET_TITLE_PHOTO",
"userDefined" : "False",
"icon" : "PRESET_ICON_PHOTO",
"settingArray" : [
{
"id" : "125",
"value" : "1",
"isCaption" : "True",
}, {
"id" : "122",
"value" : "101",
"isCaption" : "True",
}
],
"isModified" : "True",
}, {
"id" : "65538",
"mode" : "FLAT_MODE_PHOTO_BURST",
"titleId" : "PRESET_TITLE_BURST",
"userDefined" : "False",
"icon" : "PRESET_ICON_BURST",
"settingArray" : [
{
"id" : "126",
"value" : "0",
"isCaption" : "True",
}, {
"id" : "147",
"value" : "9",
"isCaption" : "True",
}, {
"id" : "123",
"value" : "101",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "65539",
"mode" : "FLAT_MODE_PHOTO_NIGHT",
"titleId" : "PRESET_TITLE_NIGHT",
"userDefined" : "False",
"icon" : "PRESET_ICON_PHOTO_NIGHT",
"settingArray" : [
{
"id" : "125",
"value" : "1",
"isCaption" : "True",
}, {
"id" : "19",
"value" : "0",
"isCaption" : "True",
}, {
"id" : "122",
"value" : "101",
"isCaption" : "True",
}
],
"isModified" : "True",
}
],
"canAddPreset" : "True",
"icon" : "PRESET_GROUP_PHOTO_ICON_ID",
}, {
"id" : "PRESET_GROUP_ID_TIMELAPSE",
"presetArray" : [
{
"id" : "131072",
"mode" : "FLAT_MODE_TIME_WARP_VIDEO",
"titleId" : "PRESET_TITLE_TIME_WARP",
"userDefined" : "False",
"icon" : "PRESET_ICON_TIMEWARP",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "111",
"value" : "10",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "131075",
"mode" : "FLAT_MODE_VIDEO_STAR_TRAIL",
"titleId" : "PRESET_TITLE_STAR_TRAIL",
"userDefined" : "False",
"icon" : "PRESET_ICON_STAR_TRAIL",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "32",
"value" : "3601",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "131076",
"mode" : "FLAT_MODE_VIDEO_LIGHT_PAINTING",
"titleId" : "PRESET_TITLE_LIGHT_PAINTING",
"userDefined" : "False",
"icon" : "PRESET_ICON_LIGHT_PAINTING",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "32",
"value" : "3601",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "131077",
"mode" : "FLAT_MODE_VIDEO_LIGHT_TRAIL",
"titleId" : "PRESET_TITLE_LIGHT_TRAIL",
"userDefined" : "False",
"icon" : "PRESET_ICON_LIGHT_TRAIL",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "32",
"value" : "3601",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "131073",
"mode" : "FLAT_MODE_TIME_LAPSE_VIDEO",
"titleId" : "PRESET_TITLE_TIME_LAPSE",
"userDefined" : "False",
"icon" : "PRESET_ICON_TIMELAPSE",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "5",
"value" : "0",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}, {
"id" : "131074",
"mode" : "FLAT_MODE_NIGHT_LAPSE_VIDEO",
"titleId" : "PRESET_TITLE_NIGHT_LAPSE",
"userDefined" : "False",
"icon" : "PRESET_ICON_NIGHTLAPSE",
"settingArray" : [
{
"id" : "2",
"value" : "102",
"isCaption" : "True",
}, {
"id" : "32",
"value" : "3601",
"isCaption" : "True",
}, {
"id" : "121",
"value" : "0",
"isCaption" : "True",
}
],
"isModified" : "False",
}
],
"canAddPreset" : "True",
"icon" : "PRESET_GROUP_TIMELAPSE_ICON_ID",
}
],
},
}
preset_statusから現在のプリセットidの情報を取得する。
presets = preset_status.data.get("presetGroupArray")
for i, preset_group in enumerate(presets):
for j, preset in enumerate(preset_group.get("presetArray")):
if preset.get("id") == active_preset_id:
print(f"preset_group: {i}, preset: {j}")
print(preset)
出力
preset_group: 1, preset: 3
{'id': 65539, 'mode': 'FLAT_MODE_PHOTO_NIGHT', 'titleId': 'PRESET_TITLE_NIGHT', 'userDefined': False, 'icon': 'PRESET_ICON_PHOTO_NIGHT', 'settingArray': [{'id': 125, 'value': 1, 'isCaption': True}, {'id': 19, 'value': 0, 'isCaption': True}, {'id': 122, 'value': 101, 'isCaption': True}], 'isModified': True}
撮影モードの設定
ナイトフォトのプリセットidを取得し、設定する。
ナイトフォトのプリセットidを取得する
上記のget_preset_statusから、ナイトフォトのプリセットのIDを探し出す。
"titleId" : "PRESET_TITLE_NIGHT"
のidを見つける。
presets = preset_status.data.get("presetGroupArray")
for i, preset_group in enumerate(presets):
for j, preset in enumerate(preset_group.get("presetArray")):
if preset.get("titleId") == "PRESET_TITLE_NIGHT":
night_preset_id = preset.get("id")
print(f"PRESET_TITLE_NIGHT id: {night_preset_id}")
出力
PRESET_TITLE_NIGHT id: 65539
ナイトフォトに設定する
preset = await gopro.http_command.load_preset(preset=night_preset_id)
print(preset)
出力
{
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/presets/load?id=65539",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
}
(参考)撮影モード(プリセットグループ)を変更する
プリセットグループを変更することで、グループ内で最後に設定されたプリセットが利用される様子。ナイトフォトに設定したあと、動画モードにし、再度、静止画モードにすると、ナイトフォトモードになる。
preset = await gopro.http_command.load_preset_group(group=Params.PresetGroup.VIDEO)
print(f"動画モード設定: {preset}")
preset = await gopro.http_command.load_preset_group(group=Params.PresetGroup.PHOTO)
print(f"静止画モード設定: {preset}")
出力
動画モード設定: {
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/presets/set_group?id=1000",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
}
静止画モード設定: {
"id" : "http://172.2X.1YZ.51:8080/gopro/camera/presets/set_group?id=1001",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
}
撮影設定
RAW撮影の設定にはhttp_settingを用いることができるが、最大ISO感度などINTERNALな設定は直接WebAPIを呼び出して設定する。
-
RAW撮影
-
ISO最小: 100
-
ISO最大: 100
-
シャープネス: 低
最大ISO感度、最小ISO感度の設定が不明なため、試してみたところ、
SettingId.INTERNAL_75
がISO最小、
SettingId.INTERNAL_24
がISO最大、
に相当する様子。IDとISO感度の関係は以下の通り。ID ISO感度 3 ISO100 2 ISO200 1 ISO400 0 ISO800 シャープネスは
SettingId.INTERNAL_117
に相当する様子。ID シャープネス 2 低 1 中 0 高
import requests
url = "http://172.2X.1YZ.51:8080/gopro/camera/setting"
# RAW撮影設定
result = await gopro.http_setting.photo_output.set(Params.PhotoOutput.RAW)
print(f"RAW撮影設定: {result}")
# ISO最小設定 (ISO 100)
querystring = {"option":"3","setting":"75"}
response = requests.request("GET", url, params=querystring)
print("Status Code:", response.status_code)
print(f"ISO最小設定: {response.text}")
# ISO最大設定 (ISO 100)
querystring = {"option":"3","setting":"24"}
response = requests.request("GET", url, params=querystring)
print("Status Code:", response.status_code)
print(f"ISO最大設定: {response.text}")
# シャープネス設定 (LOW)
querystring = {"option":"2","setting":"117"}
response = requests.request("GET", url, params=querystring)
print("Status Code:", response.status_code)
print(f"シャープネス設定: {response.text}")
出力
RAW撮影設定: {
"id" : "SettingId.PHOTO_OUTPUT",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
}
Status Code: 200
ISO最小設定: {}
Status Code: 200
ISO最大設定: {}
Status Code: 200
シャープネス設定: {}
撮影
撮影はシャッターボタンをON/OFFすることで行う。
await gopro.http_command.set_shutter(shutter=Params.Toggle.ENABLE)
await gopro.http_command.set_shutter(shutter=Params.Toggle.DISABLE)
撮影画像の取得
画像のファイルパスを取得
最後の撮影画像は get_last_captured_media で取得できそうに思ったが、エラーとなって動作しないので、手動で探すことにした。open_gopro ver.0.16.2の問題かもしれないので、将来は動作するかもしれない。
medias = await gopro.http_command.get_media_list()
# print(medias)
if medias.data is None or medias.data.media is len(medias.data.media) == 0 or medias.data.media[0].file_system is None:
print("No media found.")
exit()
file_list = []
for media in medias.data.media:
# print(media)
for file in media.file_system:
# print(file)
file_list.append(file)
# creation_timestampでソート
sorted_media = sorted(file_list, key=lambda x: int(x.creation_timestamp), reverse=True)
# 最新のファイルを取得
latest_file = sorted_media[0]
# 最新のファイル名を出力
print("Latest file:", latest_file.filename)
出力
Latest file: 100GOPRO/GOPR0569.JPG
画像のダウンロード
今回はRAW(.GPR)を取得したいが、上記の方法ではJPGしかリストアップされないため、拡張子をJPGからGPRに変更して取得する。
import pathlib
# GPRファイルパス
latest_gpr = latest_file.filename.split(".")[0] + ".GPR"
print("Downloading:", latest_gpr)
# ダウンロード先のパス
local_path = pathlib.Path(os.path.join(os.getcwd(), latest_gpr))
os.makedirs(local_path.parent, exist_ok=True)
download_file = await gopro.http_command.download_file(camera_file=latest_gpr, local_file=local_path)
print(download_file)
出力
Downloading: 100GOPRO/GOPR0569.GPR
{
"id" : "http://172.2X.1YZ.51:8080/videos/DCIM/100GOPRO/GOPR0569.GPR",
"status" : "ErrorCode.SUCCESS",
"protocol" : "Protocol.HTTP",
"data" : "/Users/xxx/gopro-test/100GOPRO/GOPR0569.GPR",
}
RAW現像
RAW(.GPR)ファイルを直接現像できなかったので、Adobe DNG ConverterでDNGに変換してから、rawpyで現像する。ここで、現像設定はデフォルトのまま。
GPR -> DNG -> PNG
import rawpy
import cv2
import os
def gpr2png(gprPath, pngPath):
# dir path
dstDir = os.path.dirname(pngPath)
if not os.path.exists(dstDir):
os.makedirs(dstDir)
gprFullPath = os.path.abspath(gprPath)
gprBaseName = os.path.basename(gprPath)
dstDirFullPath = os.path.abspath(dstDir)
# gpr to dng
dngConverter = 'C:/Program Files/Adobe/Adobe DNG Converter/DNGConverter.exe'
if os.name == 'posix':
# macOSの場合は以下のパスを使用
dngConverter = '/Applications/Adobe DNG Converter.app/Contents/MacOS/Adobe DNG Converter'
os.system(f'"{dngConverter}" {gprFullPath} -d {dstDirFullPath}')
dngFullPath = os.path.join(dstDirFullPath, gprBaseName.replace('.GPR', '.dng'))
# dng to png
with rawpy.imread(dngFullPath) as raw:
img = raw.postprocess()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imwrite(pngPath, img)
print(f"Saved: {pngPath}")
os.remove(dngFullPath)
# gpr to png
gprPath = local_path
pngPath = local_path.with_suffix('.png')
gpr2png(gprPath, pngPath)
出力
*** GPU Warning: GPU3 disabled via cr_config at init time. ***
Saved: /Users/xxx/gopro-test/100GOPRO/GOPR0569.png
まとめ
OpenGoProとそのPython SDKを使って、MacBookProとUSB接続したGoPro HERO12を制御し、RAW撮影する方法を示した。また、撮影したRAW(.GPR)ファイルを現像してPNGを取得する方法を示した。
特にOpenGoPro Python SDKはエラーや未実装が散見され、まだ完成度はそれほど高くないように思う。しかし、NCMに対応し、USBでもWifiでも同様にhttp接続できるため、Python SDKがなくてもさほど困らないかもしれない。