vision-agent 0.2.239__py3-none-any.whl → 0.2.240__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ from base64 import b64encode
8
8
  from concurrent.futures import ThreadPoolExecutor, as_completed
9
9
  from importlib import resources
10
10
  from pathlib import Path
11
- from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
11
+ from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Union, cast
12
12
  from uuid import UUID
13
13
 
14
14
  import cv2
@@ -2797,16 +2797,17 @@ def save_video(
2797
2797
  ):
2798
2798
  raise ValueError("A frame is not a valid NumPy array with shape (H, W, C)")
2799
2799
 
2800
+ output_file: IO[bytes]
2800
2801
  if output_video_path is None:
2801
- output_video_path = tempfile.NamedTemporaryFile(
2802
- delete=False, suffix=".mp4"
2803
- ).name
2802
+ output_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
2804
2803
  else:
2805
2804
  Path(output_video_path).parent.mkdir(parents=True, exist_ok=True)
2805
+ output_file = open(output_video_path, "wb")
2806
2806
 
2807
- output_video_path = video_writer(frames, fps, filename=output_video_path)
2808
- _save_video_to_result(output_video_path)
2809
- return output_video_path
2807
+ with output_file as file:
2808
+ video_writer(frames, fps, file=file)
2809
+ _save_video_to_result(output_file.name)
2810
+ return output_file.name
2810
2811
 
2811
2812
 
2812
2813
  def _save_video_to_result(video_uri: str) -> None:
@@ -1,8 +1,7 @@
1
1
  import logging
2
- import os
3
2
  import tempfile
4
3
  from functools import lru_cache
5
- from typing import List, Optional, Tuple
4
+ from typing import IO, List, Optional, Tuple
6
5
 
7
6
  import av # type: ignore
8
7
  import cv2
@@ -25,39 +24,32 @@ def _resize_frame(frame: np.ndarray) -> np.ndarray:
25
24
  def video_writer(
26
25
  frames: List[np.ndarray],
27
26
  fps: float = _DEFAULT_INPUT_FPS,
28
- filename: Optional[str] = None,
29
- file_ext: str = ".mp4",
27
+ file: Optional[IO[bytes]] = None,
30
28
  ) -> str:
31
- tempf = None
32
29
  if isinstance(fps, str):
33
30
  # fps could be a string when it's passed in from a web endpoint deployment
34
31
  fps = float(fps)
35
- if filename is None:
36
- tempf = tempfile.NamedTemporaryFile(delete=False, suffix=file_ext)
37
- filename = tempf.name
38
- container = av.open(filename, mode="w")
39
- stream = container.add_stream("h264", rate=fps)
40
- height, width = frames[0].shape[:2]
41
- stream.height = height - (height % 2)
42
- stream.width = width - (width % 2)
43
- stream.pix_fmt = "yuv420p"
44
- stream.options = {"crf": "10"}
45
- for frame in frames:
46
- # Remove the alpha channel (convert RGBA to RGB)
47
- frame_rgb = frame[:, :, :3]
48
- # Resize the frame to make dimensions divisible by 2
49
- frame_rgb = _resize_frame(frame_rgb)
50
- av_frame = av.VideoFrame.from_ndarray(frame_rgb, format="rgb24")
51
- for packet in stream.encode(av_frame):
32
+ if file is None:
33
+ file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
34
+ with av.open(file, "w") as container:
35
+ stream = container.add_stream("h264", rate=fps)
36
+ height, width = frames[0].shape[:2]
37
+ stream.height = height - (height % 2)
38
+ stream.width = width - (width % 2)
39
+ stream.pix_fmt = "yuv420p"
40
+ stream.options = {"crf": "10"}
41
+ for frame in frames:
42
+ # Remove the alpha channel (convert RGBA to RGB)
43
+ frame_rgb = frame[:, :, :3]
44
+ # Resize the frame to make dimensions divisible by 2
45
+ frame_rgb = _resize_frame(frame_rgb)
46
+ av_frame = av.VideoFrame.from_ndarray(frame_rgb, format="rgb24")
47
+ for packet in stream.encode(av_frame):
48
+ container.mux(packet)
49
+
50
+ for packet in stream.encode():
52
51
  container.mux(packet)
53
-
54
- for packet in stream.encode():
55
- container.mux(packet)
56
- container.close()
57
- # for windows nee to manually close tempfile, cannot use with NamedTemporaryFile(delete=True)
58
- if tempf is not None:
59
- tempf.close()
60
- return filename
52
+ return file.name
61
53
 
62
54
 
63
55
  def frames_to_bytes(
@@ -73,11 +65,10 @@ def frames_to_bytes(
73
65
  if isinstance(fps, str):
74
66
  # fps could be a string when it's passed in from a web endpoint deployment
75
67
  fps = float(fps)
76
- filename = video_writer(frames, fps, file_ext=file_ext)
77
- # TODO: look into memory-mapped files to avoid reading the entire file into memory
78
- with open(filename, "rb") as f:
68
+ with tempfile.NamedTemporaryFile(delete=True, suffix=file_ext) as f:
69
+ video_writer(frames, fps, f)
70
+ f.seek(0)
79
71
  buffer_bytes = f.read()
80
- os.unlink(filename)
81
72
  return buffer_bytes
82
73
 
83
74
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vision-agent
3
- Version: 0.2.239
3
+ Version: 0.2.240
4
4
  Summary: Toolset for Vision Agent
5
5
  Author: Landing AI
6
6
  Author-email: dev@landing.ai
@@ -38,7 +38,7 @@ vision_agent/tools/__init__.py,sha256=T-MPNBVbvWtfo71hobaZsdYzQ52oyymolk_OAb2Pq_
38
38
  vision_agent/tools/meta_tools.py,sha256=-heMwGkx0hX_9zUp1dgBqsJpVnl6Y6tErMsjFy0dwLM,28652
39
39
  vision_agent/tools/planner_tools.py,sha256=orBTdJQz2NKoLuX9WE6XixaYuG305xz0UBYvZOiuquQ,19474
40
40
  vision_agent/tools/prompts.py,sha256=V1z4YJLXZuUl_iZ5rY0M5hHc_2tmMEUKr0WocXKGt4E,1430
41
- vision_agent/tools/tools.py,sha256=hhQYqypvBDfcel1p4bfZHZfOZom3plnxGPHwo2T52Ls,111466
41
+ vision_agent/tools/tools.py,sha256=8J-SYpyUeqMDajF7kp2aiTeBBQrJEWGVdEsQLPAc-OM,111511
42
42
  vision_agent/utils/__init__.py,sha256=mANUs_84VL-3gpZbXryvV2mWU623eWnRlJCSUHtMjuw,122
43
43
  vision_agent/utils/agent.py,sha256=QGKcbzpAjcVj0958bXYLv07-d2i1GU7-bXVG7bTGRMA,14619
44
44
  vision_agent/utils/exceptions.py,sha256=booSPSuoULF7OXRr_YbC4dtKt6gM_HyiFQHBuaW86C4,2052
@@ -47,9 +47,9 @@ vision_agent/utils/image_utils.py,sha256=bJM2mEvB6E__M9pxi74yQYzAiZ7mu3KE2ptyVrp
47
47
  vision_agent/utils/tools.py,sha256=USZL0MKsiJgqA8RFiYRTcj_Kn2FVYKLHK4wIk0gP1Ow,7694
48
48
  vision_agent/utils/tools_doc.py,sha256=yFue6KSXoa_Z1ngCdBEc4SdPZOWF1rVLeaHu02I8Wis,2523
49
49
  vision_agent/utils/type_defs.py,sha256=BE12s3JNQy36QvauXHjwyeffVh5enfcvd4vTzSwvEZI,1384
50
- vision_agent/utils/video.py,sha256=0LsmH0sDaBWhvtV15CCJgqKxWzwDDos7Sv2wOd7wyzQ,5610
50
+ vision_agent/utils/video.py,sha256=rjsQ1sKKisaQ6AVjJz0zd_G4g-ovRweS_rs4JEhenoI,5340
51
51
  vision_agent/utils/video_tracking.py,sha256=GM9qfeawqhmZVWoKrzw5-NETd4gEo7ImMfWtBnhC3bw,12086
52
- vision_agent-0.2.239.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
53
- vision_agent-0.2.239.dist-info/METADATA,sha256=yC90fdYSDqbLrHHIU6OTm96QhNJ-39buRPoVgIxnDzM,5712
54
- vision_agent-0.2.239.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
55
- vision_agent-0.2.239.dist-info/RECORD,,
52
+ vision_agent-0.2.240.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
53
+ vision_agent-0.2.240.dist-info/METADATA,sha256=l9FlzNIT3ncQNxkIlTTUsB1aaL-7u2b1OtvYcRv0AIE,5712
54
+ vision_agent-0.2.240.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
55
+ vision_agent-0.2.240.dist-info/RECORD,,