Derr11 commited on
Commit
2fdaf8f
·
verified ·
1 Parent(s): 0341339

Create qwen_omni_utils.py

Browse files
Files changed (1) hide show
  1. qwen_omni_utils.py +125 -0
qwen_omni_utils.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import os
3
+ import requests
4
+ import io
5
+ import numpy as np
6
+ import soundfile as sf
7
+ from PIL import Image
8
+
9
+ # محاولة استيراد decord لمعالجة الفيديو، إذا لم يكن موجوداً لن يتوقف الكود بالكامل
10
+ try:
11
+ import decord
12
+ decord.bridge.set_bridge('torch')
13
+ except ImportError:
14
+ decord = None
15
+ print("Warning: 'decord' module not found. Video processing will not work.")
16
+
17
+ # محاولة استيراد librosa لمعالجة الصوت المتقدمة
18
+ try:
19
+ import librosa
20
+ except ImportError:
21
+ librosa = None
22
+
23
+ def _load_image(image_path):
24
+ """تحميل الصورة من رابط أو مسار محلي وتحويلها إلى RGB"""
25
+ if image_path.startswith("http://") or image_path.startswith("https://"):
26
+ response = requests.get(image_path, timeout=10)
27
+ image = Image.open(io.BytesIO(response.content))
28
+ else:
29
+ image = Image.open(image_path)
30
+ return image.convert("RGB")
31
+
32
+ def _load_audio(audio_path, target_sr=16000):
33
+ """تحميل الصوت وإعادة تعيين معدل الترميز (Sampling Rate)"""
34
+ if audio_path.startswith("http://") or audio_path.startswith("https://"):
35
+ response = requests.get(audio_path, timeout=10)
36
+ # استخدام io.BytesIO للقراءة من الذاكرة
37
+ audio_data, sr = sf.read(io.BytesIO(response.content))
38
+ else:
39
+ audio_data, sr = sf.read(audio_path)
40
+
41
+ # تحويل إلى Mono إذا كان Stereo
42
+ if len(audio_data.shape) > 1:
43
+ audio_data = audio_data.mean(axis=1)
44
+
45
+ # إعادة تشكيل التردد (Resampling) إذا توفر librosa وكان التردد مختلفاً
46
+ if librosa and sr != target_sr:
47
+ audio_data = librosa.resample(audio_data, orig_sr=sr, target_sr=target_sr)
48
+
49
+ return audio_data
50
+
51
+ def _load_video(video_path, n_frames=8, use_audio=True):
52
+ """معالجة الفيديو: استخراج الإطارات والصوت"""
53
+ if decord is None:
54
+ raise ImportError("Please install 'decord' to support video processing.")
55
+
56
+ # تحميل الفيديو (يدعم الروابط المباشرة في بعض إصدارات decord، ولكن يفضل تحميله مؤقتاً)
57
+ if video_path.startswith("http"):
58
+ # تحميل الملف مؤقتاً
59
+ response = requests.get(video_path, stream=True)
60
+ temp_filename = "temp_video.mp4"
61
+ with open(temp_filename, 'wb') as f:
62
+ for chunk in response.iter_content(chunk_size=1024):
63
+ if chunk:
64
+ f.write(chunk)
65
+ vr = decord.VideoReader(temp_filename)
66
+ else:
67
+ vr = decord.VideoReader(video_path)
68
+
69
+ # استخراج الإطارات (Sampling Frames)
70
+ total_frames = len(vr)
71
+ # اختيار إطارات موزعة بانتظام
72
+ frame_indices = np.linspace(0, total_frames - 1, n_frames, dtype=int)
73
+ frames = vr.get_batch(frame_indices).asnumpy()
74
+ # تحويل الإطارات إلى قائمة من صور PIL
75
+ pil_frames = [Image.fromarray(frame) for frame in frames]
76
+
77
+ audio_data = None
78
+ if use_audio:
79
+ # ملاحظة: استخراج الصوت من الفيديو يتطلب معالجة إضافية (عادة عبر ffmpeg)
80
+ # هنا سنضع قيمة فارغة لأن decord يركز على الصور،
81
+ # في التطبيقات الفعلية يتم استخدام moviepy أو ffmpeg لاستخراج المسار الصوتي
82
+ pass
83
+
84
+ return pil_frames, audio_data
85
+
86
+ def process_mm_info(conversation, use_audio_in_video=True):
87
+ """
88
+ الدالة الرئيسية لمعالجة الوسائط المتعددة.
89
+ تقوم بتحويل الروابط النصية إلى كائنات بيانات (Tensors/Images) يفهمها النموذج.
90
+ """
91
+ conversation = copy.deepcopy(conversation)
92
+ audios = []
93
+ images = []
94
+ videos = []
95
+
96
+ for message in conversation:
97
+ if "content" in message and isinstance(message["content"], list):
98
+ for item in message["content"]:
99
+ try:
100
+ if item["type"] == "audio":
101
+ # تحميل ومعالجة الصوت
102
+ audio_data = _load_audio(item["audio"])
103
+ audios.append(audio_data)
104
+
105
+ elif item["type"] == "image":
106
+ # تحميل ومعالجة الصورة
107
+ image_data = _load_image(item["image"])
108
+ images.append(image_data)
109
+
110
+ elif item["type"] == "video":
111
+ # تحميل ومعالجة الفيديو
112
+ video_frames, video_audio = _load_video(
113
+ item["video"],
114
+ use_audio=use_audio_in_video
115
+ )
116
+ videos.append(video_frames)
117
+ if use_audio_in_video and video_audio is not None:
118
+ audios.append(video_audio)
119
+
120
+ except Exception as e:
121
+ print(f"Error processing {item['type']}: {e}")
122
+ # في حالة الخطأ، يمكن تجاهل العنصر أو إضافة عنصر فارغ لتجنب انهيار الكود
123
+ pass
124
+
125
+ return audios, images, videos