mirror of
https://github.com/Pixelplanet/Pixel-VR-Player.git
synced 2026-10-23 15:01:36 +02:00
112 lines
4.4 KiB
Python
112 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Automated in-headset screenshot capture tool for Valve Steam Frame (SteamOS).
|
|
Uses OpenVR IVRScreenshots via SteamVR's running compositor to capture
|
|
both 2D preview and stereo VR framebuffers.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import time
|
|
import argparse
|
|
import subprocess
|
|
import base64
|
|
from datetime import datetime
|
|
|
|
DEFAULT_SSH_KEY = os.path.expanduser(r"~\AppData\Local\steamos-devkit\steamos-devkit\devkit_rsa")
|
|
DEFAULT_HOST = "steamos@192.168.178.61"
|
|
|
|
CPP_CODE = r"""#include <iostream>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include "/opt/steamvr/tools/hellovr_vulkan_linux/src/openvr/headers/openvr.h"
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 3) {
|
|
std::cerr << "Usage: " << argv[0] << " <preview_png> <stereo_png>" << std::endl;
|
|
return 1;
|
|
}
|
|
const char* preview = argv[1];
|
|
const char* vr_file = argv[2];
|
|
|
|
vr::EVRInitError err = vr::VRInitError_None;
|
|
vr::IVRSystem* vrSys = vr::VR_Init(&err, vr::VRApplication_Overlay);
|
|
if (!vrSys || err != vr::VRInitError_None) {
|
|
std::cerr << "VR_Init failed: " << vr::VR_GetVRInitErrorAsEnglishDescription(err) << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
vr::IVRScreenshots* vrScreenshots = (vr::IVRScreenshots*)vr::VR_GetGenericInterface("IVRScreenshots_001", &err);
|
|
if (!vrScreenshots || err != vr::VRInitError_None) {
|
|
std::cerr << "GetGenericInterface IVRScreenshots_001 failed: " << err << std::endl;
|
|
vr::VR_Shutdown();
|
|
return 1;
|
|
}
|
|
|
|
vr::ScreenshotHandle_t handle = 0;
|
|
vr::EVRScreenshotError scErr = vrScreenshots->TakeStereoScreenshot(&handle, preview, vr_file);
|
|
if (scErr != vr::VRScreenshotError_None) {
|
|
std::cerr << "TakeStereoScreenshot failed with error: " << scErr << std::endl;
|
|
vr::VR_Shutdown();
|
|
return 1;
|
|
}
|
|
std::cout << "Screenshot requested successfully, handle: " << handle << std::endl;
|
|
|
|
// Allow compositor frame loop to flush the write
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
|
|
|
vr::VR_Shutdown();
|
|
return 0;
|
|
}
|
|
"""
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Capture in-headset screenshots from Valve Steam Frame")
|
|
parser.add_argument("--host", default=DEFAULT_HOST, help="Steam Frame SSH destination")
|
|
parser.add_argument("--key", default=DEFAULT_SSH_KEY, help="Path to devkit private key")
|
|
parser.add_argument("--delay", type=int, default=0, help="Seconds to wait before taking screenshot")
|
|
parser.add_argument("--out-dir", default="docs/screenshots", help="Directory to save downloaded screenshots")
|
|
args = parser.parse_args()
|
|
|
|
if args.delay > 0:
|
|
print(f"Waiting {args.delay} seconds before capture (put headset on or position UI)...")
|
|
time.sleep(args.delay)
|
|
|
|
b64_cpp = base64.b64encode(CPP_CODE.encode('utf-8')).decode('utf-8')
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
remote_preview = f"/tmp/pixelvr_snap_{timestamp}_preview.png"
|
|
remote_stereo = f"/tmp/pixelvr_snap_{timestamp}_stereo.png"
|
|
|
|
remote_cmd = (
|
|
f"if [ ! -f /tmp/pixelvr_screenshot_bin ]; then "
|
|
f" echo '{b64_cpp}' | base64 -d > /tmp/pixelvr_screenshot.cpp && "
|
|
f" g++ -O2 /tmp/pixelvr_screenshot.cpp -L/opt/steamvr/bin/linuxarm64 -lopenvr_api -Wl,-rpath,/opt/steamvr/bin/linuxarm64 -o /tmp/pixelvr_screenshot_bin ; "
|
|
f"fi ; "
|
|
f"/tmp/pixelvr_screenshot_bin {remote_preview} {remote_stereo}"
|
|
)
|
|
|
|
print(f"Triggering screenshot capture on {args.host}...")
|
|
res = subprocess.run([
|
|
"ssh", "-i", args.key, "-o", "StrictHostKeyChecking=no", args.host, remote_cmd
|
|
], capture_output=True, text=True)
|
|
|
|
if res.returncode != 0:
|
|
print("Error capturing screenshot:\n", res.stderr)
|
|
sys.exit(1)
|
|
|
|
print(res.stdout.strip())
|
|
|
|
os.makedirs(args.out_dir, exist_ok=True)
|
|
local_preview = os.path.join(args.out_dir, f"screenshot_{timestamp}_preview.png")
|
|
local_stereo = os.path.join(args.out_dir, f"screenshot_{timestamp}_stereo.png")
|
|
|
|
print(f"Downloading captured frames to {args.out_dir}...")
|
|
subprocess.run(["scp", "-i", args.key, "-o", "StrictHostKeyChecking=no", f"{args.host}:{remote_preview}", local_preview], check=True)
|
|
subprocess.run(["scp", "-i", args.key, "-o", "StrictHostKeyChecking=no", f"{args.host}:{remote_stereo}", local_stereo], check=True)
|
|
|
|
print(f"Saved: {local_preview}")
|
|
print(f"Saved: {local_stereo}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|