في الآونة الأخيرة ، قام FFMPegframeGrabber Frame Capturer باستخدام حزمة FFMPEG من JAVACV بمزامنة إطارات الصوت التي تم التقاطها وإطارات الفيديو. طريقة التزامن المستخدمة هي مزامنة الفيديو مع الصوت.
البرامج ورموز المصدر
الأفكار المحددة هي كما يلي:
(1) قدم أولاً كيف تلتقط FFMPEG صور وأصوات ملفات الفيديو
FFMPegFrameGrabber fg = new FFMPegFrameGrabber ("مسار ملف الفيديو أو عنوان URL) ؛ بعد الحصول على كائن التقاط الإطار ، سيعود استدعاء طريقة Grab () إلى كائن الإطار الملتقط. يمكن أن يكون هذا الإطار إطارًا فيديو أو إطارًا صوتيًا ، لأن إطارات الصوت والفيديو مرتبة أولاً في وقت التشغيل وفقًا لمادة الطابع الزمني. بالطبع ، يتم فك تشفير جميع الإطارات التي تم التقاطها وتخزينها في كائن Java.nio.buffer. بالنسبة لإطارات الفيديو ، فإن المخزن المؤقت هو تخزين بيانات البكسل للصورة ، مثل RGB ، ثم تمرير
BufferedImage BI = (New Java2DframeConverter ()). getBufferedImage (F) ؛
يمكنك الحصول على الصورة ، ويمكن معالجة الصورة التي تم الحصول عليها في سلسلة من العمليات أو عرضها مباشرة على مكون التأرجح دون معالجة. المقابلة لإطار الصوت ، المخزن المؤقت هو بيانات PCM التي تخزن الصوت. يمكن أن يكون هذا PCM يطفو أو قصيرًا ، ثم طريقة sourcedataline.write في java.sounds.sample يمكن استخدامها لكتابة بيانات PCM الصوتية هذه إلى السماعة.
(2) ثم قدم كيفية تشغيل الإطارات التي تم الحصول عليها باستمرار. أولاً ، قم بتشغيل الفيديو بشكل منفصل:
بينما (صواب) {frame f = fg.grab () ؛ if (f.image! = null) label.seticon (new imageicon ((new Java2DframeConverter ()). getBufferedImage (f))) ؛ thread.sleep (1000/معدل إطار الفيديو) ؛ } وينطبق الشيء نفسه على تشغيل الصوت بشكل منفصل ، ما عليك سوى كتابة البيانات إلى بطاقة الصوت. مثال
(3) الإنتاج ونموذج المستهلك.
الصورة أعلاه هي طريقة تنفذها البرنامج. يتم الحكم على الإطارات التي تم التقاطها باستخدام وضع المنتج. إذا كان إطار فيديو ، فسيتم إنتاجه في الفيديو FIFO. إذا كان إطارًا صوتيًا ، فسيتم إنتاجه في الصوت FIFO. ثم يستهلك مؤشر ترابط تشغيل الصوت وخيط تشغيل الفيديو الإطارات من مستودعات الإطار الخاصة به على التوالي. تم اعتماد وضع المستهلك للإنتاج لأن سرعة التقاط الإطار أكبر من استهلاك الإطارات ، لذلك نحن نفضل التقاط الإطارات للتخزين المؤقت ، أو مزيد من المعالجة المسبقة للإطارات الملتقطة ، في حين أن خيوط تشغيل الفيديو والصوت تحتاج فقط إلى تشغيل وعرض الإطارات المعالجة مباشرة.
(4) طرق لتحقيق مزامنة الصوت والفيديو: قم بتشغيل جميع إطارات الفيديو في إطارين من الصوت.
لتحقيق مزامنة الصوت والفيديو ، يجب أن يكون لديك طابع زمني للإطار. الإطارات التي تم التقاطها هنا ليست سوى نقاط الطوابع الزمنية للتشغيل ، ولا توجد DTS من طابع زمنية فكرية ، لذلك نحتاج فقط إلى اتخاذ قرار في الطابع الزمني للتشغيل استنادًا إلى الطابع الزمني للتشغيل.
يعتمد تنفيذ البرنامج على الرقم أعلاه. عندما يبدأ مؤشر ترابط الصوت في تشغيل إطار الصوت A1 ، يتم استدعاء طريقة SetRun لخيط الفيديو ، ويتم تمرير Curtime TimeStamp Timestamp ، والطابع الزمني التالي لإطار الصوت التالي A2 إلى مؤشر ترابط الفيديو في حالة الانتظار. ثم يبدأ مؤشر ترابط الفيديو ويبدأ في إخراج إطار الفيديو G1 من الفيديو FIFO ، ثم يحسب الفرق الزمني بين G1 و A1 كتأخير التشغيل. بعد Thread.sleep (T1) ، يعرض مؤشر ترابط الفيديو الصورة على مكون التأرجح ، مثل jlabel.seticon (الصورة). ثم يأخذ مؤشر ترابط الفيديو إطارًا آخر من الصورة G2 ويقارن الطابع الزمني لـ G2 مع الطابع الزمني لـ A2. إذا كان الطابع الزمني لـ G2 أقل من A2 ، يستمر مؤشر ترابط الفيديو في تأخير T2 ويلعب صورة G2. ثم G3 هو نفسه كما ينبغي ، حتى يتم الحصول على G4 ويتم مقارنة A2 بـ A2 ويجد أن الطابع الزمني لـ G4 أكبر من A2 ، ثم يدخل مؤشر ترابط الفيديو إلى حالة الانتظار وينتظر بدء التشغيل التالي. ثم بعد أن يلعب مؤشر ترابط الصوت إطار الصوت A1 ، يأخذ إطار الصوت A3 من المستودع ، ثم يمرر الطابع الزمني لـ A2 و Timestamps من A3 إلى سلسلة الفيديو ، ثم يبدأ تشغيل A2 ، ثم يستمر سلسلة الفيديو المحظورة في اللعب.
(5) ضبط وقت التأخير ديناميكي
نظرًا لأن أجهزة الكمبيوتر الشخصية ليست أنظمة تشغيل في الوقت الفعلي ، أي أن thread.sleep غير دقيق ومقيد بواسطة بطاقة الصوت لتشغيل الصوت ، يجب تحسين أفكار التنفيذ الأساسية أعلاه. بادئ ذي بدء ، تتمثل طريقة Java Sourcedataline في استخراج البيانات المكتوبة بواسطة مؤشر ترابط الصوت من المخزن المؤقت الداخلي بسرعة معينة. إذا تم إخراج البيانات التي كتبها الصوت ، فسيتم تشغيل تشغيل الصوت. ومع ذلك ، إذا تم كتابة الكثير من بيانات الصوت في وقت واحد ، فقد يكون الصوت والفيديو خارجا عن التزامن. لذلك ، من الضروري التأكد من أن المخزن المؤقت الداخلي لـ Sourcedataline لديه بيانات معينة ، وإلا فإنه سيؤدي إلى تأخر ، ولكن لا يمكن أن يكون مقدار البيانات أكثر من اللازم. لذلك ، نقوم بضبط تشغيل الصوت من G3 إلى A2. نظرًا لعدم دقة التأخير ، قد تتم إزالة البيانات المكتوبة في إطار A1 بواسطة بطاقة الصوت قبل أن يصل الوقت إلى T6. لذلك ، بعد تشغيل صورة G3 ، سيحكم مؤشر ترابط الصوت على الحكم بناءً على مقدار البيانات التي يتم إرجاعها بواسطة sourcedataline.available (). إذا كانت كمية البيانات على وشك الانتهاء ، يتم تقليل وقت التأخير T4 من G3 إلى A2. هذا يضمن أن حجم البيانات لن يتغير إلى 0 ويتسبب في تأثر الصوت.
(6) ما يلي هو مخطط النتائج لاختبار البرنامج ضمن نظام التشغيل Windows 64 و Ubuntu14: التشغيل سلس نسبيًا ، والمزامنة ممكنة أيضًا ، ولكن إذا تم تشغيل التشغيل ، فسيتم عالقه إذا كتبت البطريق رمزًا في IDE مثل IDEA. بعد كل شيء ، تم تطوير Idea أيضًا في Java ، وبالتالي فإن تشغيل Idea سيؤثر على برامج Java الأخرى ، لكن عمليات أخرى لن تفعل ذلك.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.