Video and Log Synchronization for Hardware Tests
Measurements tell you what happened. Videos and logs tell you why. A failed vibration test makes more sense when you can watch the unit rattle loose. A firmware crash is easier to debug when the serial console log is right next to the test result. TofuPilot stores attachments alongside measurements.
Why Attachments Matter
A measurement value of "FAIL" tells you something broke. But it doesn't tell you:
- What the unit physically looked like during the test
- What the firmware logged before the crash
- What the oscilloscope waveform looked like
- What the operator saw on their screen
Attachments bridge this gap. They turn a test result from a number into a complete record of what happened.
Types of Test Attachments
| Attachment type | Use case | Format |
|---|---|---|
| Video recording | Visual inspection, mechanical tests | MP4, AVI |
| Serial console log | Firmware debug, boot sequence | TXT, LOG |
| Oscilloscope capture | Waveform analysis, timing | PNG, CSV |
| Thermal image | Hot spot detection | JPEG, PNG |
| Test station log | Test software debug | TXT, LOG |
| Configuration file | DUT or fixture settings | JSON, YAML |
| Photo | Physical defect documentation | JPEG, PNG |
Attaching Files to Test Runs
With the Python Client
from tofupilot import TofuPilotClient
client = TofuPilotClient()
client.create_run(
procedure_id="VIBRATION-SCREENING",
unit_under_test={"serial_number": "UNIT-7832"},
run_passed=False,
steps=[{
"name": "Random Vibration 20-2000Hz",
"step_type": "measurement",
"status": False,
"measurements": [{
"name": "resonance_freq_hz",
"value": 847,
"unit": "Hz",
"limit_low": 900,
"limit_high": 1500,
}],
}],
attachments=[
"recordings/unit-7832-vibration.mp4",
"logs/unit-7832-accel.csv",
"captures/unit-7832-spectrum.png",
],
)Capturing Video Automatically
Record video during the test and attach it to the run.
import subprocess
import os
def start_recording(output_path):
"""Start recording from a USB camera."""
proc = subprocess.Popen([
"ffmpeg", "-f", "v4l2", "-i", "/dev/video0",
"-t", "120", # max 2 minutes
"-y", output_path,
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return proc
def stop_recording(proc):
"""Stop the recording."""
proc.terminate()
proc.wait()
# Usage in a test
video_path = f"/tmp/test_{serial}.mp4"
recorder = start_recording(video_path)
# Run the test...
run_test()
stop_recording(recorder)
# Attach to TofuPilot run
client.create_run(
procedure_id="MECHANICAL-TEST",
unit_under_test={"serial_number": serial},
run_passed=passed,
steps=steps,
attachments=[video_path],
)Capturing Serial Console Logs
import serial
import threading
class SerialLogger:
def __init__(self, port, baudrate=115200):
self.ser = serial.Serial(port, baudrate, timeout=1)
self.log = []
self.running = False
def start(self):
self.running = True
self.log = []
self.thread = threading.Thread(target=self._read_loop)
self.thread.start()
def stop(self):
self.running = False
self.thread.join()
self.ser.close()
def _read_loop(self):
while self.running:
line = self.ser.readline().decode("utf-8", errors="replace")
if line:
self.log.append(line)
def save(self, path):
with open(path, "w") as f:
f.writelines(self.log)
# Usage
logger = SerialLogger("/dev/ttyUSB0")
logger.start()
# Run the test...
run_test()
logger.stop()
log_path = f"/tmp/console_{serial}.log"
logger.save(log_path)
# Attach to TofuPilot
client.create_run(
procedure_id="FIRMWARE-VALIDATION",
unit_under_test={"serial_number": serial},
run_passed=passed,
steps=steps,
attachments=[log_path],
)Synchronized Review
When you open a test run in TofuPilot, all attachments are available alongside the measurements. This synchronized view lets you:
- See that
resonance_freq_hzfailed at 847 Hz (below the 900 Hz limit) - Watch the video to see the enclosure flexing during the test
- Open the accelerometer CSV to see the raw vibration data
- Check the spectrum plot to identify the resonant mode
All in one place, for one run, with one click.
When to Attach What
Not every test needs video and logs. Attachments add storage and complexity. Use them where they add diagnostic value.
| Test type | Recommended attachments |
|---|---|
| Vibration/shock | Video, accelerometer data |
| Firmware validation | Serial console log |
| Visual inspection | Photo of DUT |
| Power testing | Oscilloscope captures |
| Environmental testing | Temperature/humidity logs |
| Burn-in | All logs (long-duration, hard to reproduce) |
For routine production tests (ICT, basic functional), measurements alone are usually sufficient. Save attachments for tests where visual or log context helps debugging.
Storage Considerations
| Practice | Why |
|---|---|
| Compress videos before attaching | Reduce storage costs |
| Keep attachments under 50MB per run | Practical upload/download speed |
| Use PNG for plots, JPEG for photos | PNG for clarity, JPEG for size |
| Only attach to failing runs (optionally) | Save storage on passing runs where attachments are rarely reviewed |
| Include timestamps in log files | Correlate log events with test step timing |