You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

lerobot_webcam_saver.py 2.7 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. """Module for saving webcam feed data from LeRobot experiments.
  2. This module provides functionality for capturing and saving webcam feed data
  3. during LeRobot experiments with the Reachy robot.
  4. """
  5. #!/usr/bin/env python3
  6. import os
  7. import subprocess
  8. from pathlib import Path
  9. import cv2
  10. import pyarrow as pa
  11. from dora import Node
  12. node = Node()
  13. CAMERA_NAME = os.getenv("CAMERA_NAME", "camera")
  14. CAMERA_WIDTH = 1280
  15. CAMERA_HEIGHT = 800
  16. FPS = 30
  17. i = 0
  18. episode = -1
  19. dataflow_id = node.dataflow_id()
  20. BASE = Path("out") / dataflow_id / "videos"
  21. out_dir = BASE / f"{CAMERA_NAME}_episode_{episode:06d}"
  22. for event in node:
  23. event_type = event["type"]
  24. if event_type == "INPUT":
  25. if event["id"] == "record_episode":
  26. record_episode = event["value"].to_numpy()[0]
  27. print(f"Recording episode {record_episode}", flush=True)
  28. # Save Episode Video
  29. if episode != -1 and record_episode == -1:
  30. out_dir = BASE / f"{CAMERA_NAME}_episode_{episode:06d}"
  31. fname = f"{CAMERA_NAME}_episode_{episode:06d}.mp4"
  32. video_path = BASE / fname
  33. # Save video
  34. ffmpeg_cmd = (
  35. f"ffmpeg -r {FPS} "
  36. "-f image2 "
  37. "-loglevel error "
  38. f"-i {out_dir / 'frame_%06d.png'!s} "
  39. "-vcodec libx264 "
  40. "-g 2 "
  41. "-pix_fmt yuv444p "
  42. f"{video_path!s} &&"
  43. f"rm -r {out_dir!s}"
  44. )
  45. print(ffmpeg_cmd, flush=True)
  46. subprocess.Popen([ffmpeg_cmd], start_new_session=True, shell=True)
  47. episode = record_episode
  48. # Make new directory and start saving images
  49. elif episode == -1 and record_episode != -1:
  50. episode = record_episode
  51. out_dir = BASE / f"{CAMERA_NAME}_episode_{episode:06d}"
  52. out_dir.mkdir(parents=True, exist_ok=True)
  53. i = 0
  54. else:
  55. continue
  56. elif event["id"] == "image":
  57. # Only record image when in episode.
  58. # Episode 0 is for not recording periods.
  59. if episode == -1:
  60. continue
  61. fname = f"{CAMERA_NAME}_episode_{episode:06d}.mp4"
  62. node.send_output(
  63. "saved_image",
  64. pa.array([{"path": f"videos/{fname}", "timestamp": i / FPS}]),
  65. event["metadata"],
  66. )
  67. image = event["value"].to_numpy().reshape((CAMERA_HEIGHT, CAMERA_WIDTH, 3))
  68. path = str(out_dir / f"frame_{i:06d}.png")
  69. cv2.imwrite(path, image)
  70. i += 1