البحث عن توقيت البداية والنهاية لِـ مقطع صوتي فريد في الفيديو باستخدام لغة بايثون.

  • Kakarotto

السلام عليكم ورحمة الله وبركاته.

  • لديّ مقطع صوتي مدته حوالي الـ 5 ثوان استخرجته من الفيديو (نفس ملف الفيديو المذكور بالأسفل).
  • ليكن اسم الملف الصوتيّ:
 a.wav
  • الفيديو وليكن اسمه:
video.mp4
  • محتوى هذا الفيديو فيه يتكرّر المقطع الصوتي القصير السابق كيف يمكنني باستخدام لغة بايثون أن أجد مكان تواجد هذا الجزء من الصوت في الفيديو وطباعة وقت البداية ووقت النهاية؟

من لديه فكرة أو مكتبة أو كود يُفيد لهذا الغرض ليخبرنا جزاكم الله كلّ خير ♥


Mohammed_Emad أضف ردا

وعليكم السلام ورحمه الله

يمكن البحث داخل مقطع الفيديو بطريقتين وربما اكثر

أول تلك الطرق هي استخدام احد مكتبات او محركات التعرف علي الكلام speech recognition ,في تحويل المقطع الي نص ثم البحث عن المقطع الصوتي القصير بداخله ,

ولكن هذه الطريقة قد لا تكون دقيقة تماما اذا كان المقطع مشوش اكثر من اللازم او بلهجة عامية او اذا كان المقطع المنشود لا يوجد به كلام..

الطريقة الثانية:

وهي البحث عن بصمة المقطع ذاته باستخدام librosa ,

تعمل librosa علي تحويل المقاطع الصوتية الي array او map يسهل التنقل بداخلها,

ثم استخدام تحليل فورييه للبحث عن الترابط "correlate" بين ميزات المقطع الصوتي القصير واجزاء المقطع الرئيسي او الطويل.

يمكن حساب الترابط بسهولة من خلال عدة مكتبات في بايثون سواء numpy او scipy ,

لكن سيكون عليك تحويل مقطع الفيديو الي wav قبل هذه العملية يمكنك اجراء ذلك عن طريق ffmpeg والأمر التالي:

ffmpeg -i wissal_idb.mp4 -vn -acodec pcm_s16le -ar 44100 -ac 2 video.wav

وإذا كان المقطع من نوع mp3 يمكنك التحويل بإستخدام

ffmpeg -i input.mp3 -acodec pcm_s16le -ac 1 -ar 16000 output.wav

يمكنك تثبيت ffmpeg من هنا https://www.ffmpeg.org/down...

وفيما يلي مثال علي الفكرة التي ذكرتها:

from scipy import signal
import numpy as np
import librosa

def get_loc_clib(full_clib, small_clib):
    y_full, sr_full = librosa.load(full_clib, sr=None) #load file
    y_small, sr_small = librosa.load(small_clib, sr=sr_full)#load file
    full_Duration = librosa.get_duration(y=y_full, sr=sr_full)
    small_Duration = librosa.get_duration(y=y_small, sr=sr_small)
    end_search = int(full_Duration)
    correlate = signal.correlate(y_full, y_small[:sr_full*end_search], mode='valid', method='fft')
    start = np.round(np.argmax(correlate) / sr_full, 2)
    end = start+small_Duration

    print("Start:{} |s".format(start))
    print("End:{:.2f} | s".format(end))


if __name__ == '__main__':
   get_loc_clib("video.wav", "a.wav")

علي سبيل المثال الناتج سيكون هكذا:

Full  Audio Duration:595.32 | s
Small Audio Duration:15.104 | s
The moment the search stops in seconds:  595
Start:200.0 |s
End:215.10 | s

ويمكن حصر البحث داخل جزء من المقطع بدلا من البحث في كامل المقطع من خلال تغيير قيمة المتغير end_search ,هي الان تستخدم full_Duration اي الزمن الكامل للمقطع الذي نبحث بداخله.

إذا اردت تطوير الكود اكثر من ذلك اطلع علي الفكرة الكاملة هنا

بالتوفيق.

جزاك اللّه كلّ خير ما شاء الله شرح وإجابة وافية ♥

إذا كان الصوت مكرّراً بالفيديو أكثر من مرّة فكيف سأدعم هذا الموضوع من فضلك وهل هذه الطريقة لا تستهلك الكثير من موارد الجهاز ؟ أتحدث عن الطريقة 2.