liuguilin commited on
Commit
2447c5c
·
1 Parent(s): 107b53d
Files changed (1) hide show
  1. eagle_vl/serve/chat_utils.py +48 -24
eagle_vl/serve/chat_utils.py CHANGED
@@ -23,36 +23,57 @@ import tempfile
23
  import os
24
  import imageio
25
 
26
- def compress_video_to_base64(video_path: str, max_frames=128, resolution=(960, 540)) -> str:
 
 
 
 
 
 
27
  cap = cv2.VideoCapture(video_path)
28
- total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
 
 
 
 
 
 
 
 
 
29
  step = max(1, total_frames // max_frames)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- frames = []
32
- count = 0
33
- while cap.isOpened():
34
  ret, frame = cap.read()
35
  if not ret:
36
  break
37
- if count % step == 0:
38
- frame_resized = cv2.resize(frame, resolution)
39
- frames.append(cv2.cvtColor(frame_resized, cv2.COLOR_BGR2RGB))
40
- count += 1
41
- cap.release()
42
-
43
- with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
44
- tmp_path = tmp.name
45
 
46
- writer = imageio.get_writer(tmp_path, fps=10, codec='libx264', quality=8) # quality: 0(worst) - 10(best)
47
- for f in frames:
48
- writer.append_data(f)
49
  writer.close()
50
 
51
  with open(tmp_path, "rb") as f:
52
- video_data = f.read()
53
  os.remove(tmp_path)
54
-
55
- return base64.b64encode(video_data).decode("utf-8")
56
 
57
 
58
 
@@ -448,11 +469,14 @@ def to_gradio_chatbot(conversation: Conversation) -> list:
448
  # Fallback to link
449
  media_str += f'<a href="{item}" target="_blank">{item}</a>'
450
  elif isinstance(item, str) and (item.endswith((".mp4", ".mov", ".avi", ".webm"))):
451
- b64 = compress_video_to_base64(item)
452
- media_str += (
453
- f'<video controls style="max-width:300px;height:auto;" '
454
- f'src="data:video/mp4;base64,{b64}"></video>'
455
- )
 
 
 
456
 
457
  # If PIL image
458
  else:
 
23
  import os
24
  import imageio
25
 
26
+
27
+ def compress_video_to_base64(
28
+ video_path: str,
29
+ max_frames: int = 128,
30
+ resolution: tuple = (960, 540),
31
+ target_crf: int = 28
32
+ ) -> str:
33
  cap = cv2.VideoCapture(video_path)
34
+ if not cap.isOpened():
35
+ raise RuntimeError(f"无法打开视频:{video_path}")
36
+
37
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) or None
38
+ original_fps = cap.get(cv2.CAP_PROP_FPS) or None
39
+
40
+ if not total_frames or not original_fps:
41
+ cap.release()
42
+ raise RuntimeError("无法获取视频帧数或帧率,请检查视频文件或使用 ffprobe。")
43
+
44
  step = max(1, total_frames // max_frames)
45
+ new_fps = max(1, round(original_fps / step))
46
+
47
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
48
+ tmp_path = tmp.name
49
+
50
+ writer = imageio.get_writer(
51
+ tmp_path,
52
+ fps=new_fps,
53
+ codec='libx264',
54
+ ffmpeg_params=[
55
+ '-crf', str(target_crf),
56
+ '-pix_fmt', 'yuv420p'
57
+ ]
58
+ )
59
 
60
+ frame_idx = 0
61
+ while True:
 
62
  ret, frame = cap.read()
63
  if not ret:
64
  break
65
+ if frame_idx % step == 0:
66
+ small = cv2.resize(frame, resolution)
67
+ writer.append_data(cv2.cvtColor(small, cv2.COLOR_BGR2RGB))
68
+ frame_idx += 1
 
 
 
 
69
 
70
+ cap.release()
 
 
71
  writer.close()
72
 
73
  with open(tmp_path, "rb") as f:
74
+ data = f.read()
75
  os.remove(tmp_path)
76
+ return base64.b64encode(data).decode("utf-8")
 
77
 
78
 
79
 
 
469
  # Fallback to link
470
  media_str += f'<a href="{item}" target="_blank">{item}</a>'
471
  elif isinstance(item, str) and (item.endswith((".mp4", ".mov", ".avi", ".webm"))):
472
+ try:
473
+ b64 = compress_video_to_base64(item)
474
+ media_str += (
475
+ f'<video controls style="max-width:300px;height:auto;" '
476
+ f'src="data:video/mp4;base64,{b64}"></video>'
477
+ )
478
+ except:
479
+ pass
480
 
481
  # If PIL image
482
  else: