لذلك ، انتقل إلى خط النهاية. لقد
تعلمنا بالفعل
كيفية دفق الفيديو من android إلى مشغل VLC ، والآن يبقى فقط دمج النافذة مع الفيديو في تطبيق JAVA والبدء في توجيه الروبوت.

المشروع المفتوح المصدر
VLCJ CAPRICA سوف يساعدنا كثيرا في
هذا .
يوفر مشروع vlcj إطار عمل Java للسماح بإدراج مثيل لمشغل وسائط VLC أصلي في تطبيق Java.
فكرة الرجال بسيطة ، ولكنها بارعة (فلفل حقيقي). بدلاً من تعذُّب مكتبات FFmpeg وغيرها ، يجب عليك على الفور الاتصال
بالمتخصص جوهر مشغل وسائط VLC عادي وعملي ومحترف. واتصل بها مباشرة من تطبيق JAVA.
من يهتم ، نسأل عن القط.
نظرًا لوجود الكثير من المزالق في هذه الرحلة ، سنبدأ ، كالعادة ، بحركة بسيطة للغاية وبعد ذلك ننتقل إلى التافهة.
تثبيت حزمة VLCJ
أولاً ، تحقق من إصدار مشغل وسائط VLC. لا نحتاج إلى إصدار جديد ، فهو يقطع ما هو مطلوب لتيار البث المباشر. وقد ذكر هذا بالفعل في
وظيفة سابقة . لذلك ، نقوم بتنزيل الإصدار
2.2.6 من المظلة وفي نفس الوقت نتفحص بعناية حزمة JAVA الخاصة بنا. يجب أن تتطابق في عمق بت. إذا كان المشغل يستخدم بنية 64 بت ، فيجب أن يكون JDK هو نفسه. ولن تقلع.
بعد ذلك ، يمكنك بالفعل تنزيل
حزمة مكتبة VLCJ نفسها

يرجى ملاحظة أننا بحاجة إلى
حزمة توزيع (zip) vlcj-3.12.1 . هو الذي يعمل مع لاعبين نسخة VLC 2.2.x. يمكنك فك الضغط في أي مكان ، والشيء الرئيسي هو أنه ليس في مجلد VLC نفسه ، لأن الملفين يتطابقان مع الاسم. وإذا قمت بإعادة كتابتها ، فسوف ينتهي كل هذا بالفشل التام.
بعد ذلك ، نقوم بإنشاء مشروع في IntelliJ IDEA IDE (إذا كان لديك IDE مختلف ، لا يمكنني مساعدة أي شيء) وكتابة التبعيات اللازمة لدمج مكتبات VLCJ.

نحن نفعل ذلك فقط للملفات:
الجيش الشعبي اليوغوسلافي-5.2.0
الجيش الشعبي اليوغوسلافي منصة-5.2.0
vlcj-3.12.1ثم ننشئ الفصل الوحيد ونكتب البرنامج الصغير التالي فيه.
import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent; import uk.co.caprica.vlcj.discovery.NativeDiscovery; import uk.co.caprica.vlcj.player.MediaPlayerFactory; import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer; import uk.co.caprica.vlcj.player.embedded.videosurface.CanvasVideoSurface; public class BasicPlayer { public final JFrame frame; public static String mrl; public static MediaPlayerFactory mpf; public static EmbeddedMediaPlayer MediaPlayer; public static CanvasVideoSurface videoSurface; public static Canvas canvas; public static void main(final String[] args) { new NativeDiscovery().discover(); mrl = "D:\\ttt.mp4"; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { BasicPlayer vp = new BasicPlayer(); vp.start(mrl); } }); } public BasicPlayer() { frame = new JFrame("My First Media Player"); frame.setBounds(200, 100, 540, 340); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.out.println(e); MediaPlayer.release(); mpf.release(); System.exit(0); } }); JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); canvas = new Canvas(); mpf = new MediaPlayerFactory(); videoSurface = mpf.newVideoSurface(canvas); MediaPlayer = mpf.newEmbeddedMediaPlayer(); MediaPlayer.setVideoSurface(videoSurface); contentPane.add(canvas, BorderLayout.CENTER);
نعم ، بينما نحاول تشغيل ملف فقط (كما يظهر من الكود). من الأفضل عدم البدء بـ udp - إنه لن ينجح. ويتم تشغيل الملف بالكامل إذا ، بالطبع ، لم تنسَ وضعه مع الاسم المقابل مقدمًا عند الضرورة. أعتقد أنه حتى بالنسبة إلى معظم javista المبتدئ ، لن يكون من الصعب فهم الرمز أعلاه.
الجديد هو:
دعوة ل VLCJ new NativeDiscovery().discover();
وإنشاء مثيل مشغل الوسائط نفسه mpf = new MediaPlayerFactory(); videoSurface = mpf.newVideoSurface(canvas); MediaPlayer = mpf.newEmbeddedMediaPlayer(); MediaPlayer.setVideoSurface(videoSurface);
ثم نضيفها فقط إلى لوحة الرسوم المطلوبة:
contentPane.add(canvas, BorderLayout.CENTER);
وكل شيء ، سيتم تشغيل الملف في هذه النافذة.
الآن حاول استبدال
mrl = "D:\\ttt.mp4";
في
mrl = "udp://@:40002";
كما فعلنا بهدوء في آخر مشاركة لبث الفيديو عبر اتصال UDP.
هذا الرقم لن يعمل هنا. بطبيعة الحال ، ستفتح النافذة ، لكنها ستظهر التين ، بمعنى الشاشة الداكنة. على الرغم من أنه لن يكون هناك سجلات خطأ. لن يكون هناك أي شيء.
فلدي الرقم بها
ربما برنامج الترميز H264 الذي حددناه في الإعدادات مفقود؟ توقف ، كيف إذن لعب ملف ttt.mp4؟ لا يستطيع اللعب مع هذا الإعداد ، فهو MP4.
يأتي على الفور فهم أن مكتبة VLCJ تدير فقط جوهر اللاعب نفسه. وما هي الإعدادات المسبقة هناك ، فهي لا تعرف ولا تريد أن تعرف. هذا هو ، نحن بحاجة ، بطريقة ما ، عند بدء تشغيل تطبيق JAVA ، إلى حد ما بتمرير مشغل VLC الذي نريده باستخدام برنامج الترميز H264 بشكل صريح أو ، على سبيل المثال ، نريد تدوير الصورة أو أي شيء آخر.
اتضح أنه يمكن القيام بذلك باستخدام فئة MediaPlayerFactory. فقط أطلقناها دون جدال ، أو حتى معهم. على موقع
stackoverflow.com ، وجدت على الفور مثالًا بسيطًا يتعلق بتدوير الصور:
String[] args = { "--video-filter", "rotate", "rotate-angle", "10" }; mpf = new MediaPlayerFactory(args);
أي أننا ننقل شيئًا ما مع صفيف سلسلة إلى مصنع الوسائط ويتم تخزينه هناك لمورد الوسائط المستخدم.
حاولت هذه الطريقة لتشغيل الملف وكالعادة ، لا شيء يعمل. اتضح أنهم نسوا إضافة شرطيتين ونشرهما في جميع أنحاء الإنترنت. كان علي أن أخمن باستخدام طريقة تحويل مماثلة.
باختصار ، يجب أن يكون:
String[] args = { "--video-filter", "rotate", "--rotate-angle", "10" };
الآن عاد ملفنا المرجعي كما ينبغي!

علاوة على ذلك ، سيكون الأمر بسيطًا جدًا:
لتحديد برنامج الترميز ، وفقًا
لسطر الأوامر VLC ، نضيف السطر إلى صفيف السلسلة:
"--demux=h264"
جرب قناة UDP مرة أخرىmrl = "udp: // @: 40002"؛
وهذه المرة يعمل كل شيء ، مما يدل على انتصار العقل البشري. الآن نافذة الفيديو هذه أو العديد من هذه النوافذ ، يمكنك بسهولة الوصول إلى الواجهة الرسومية لتطبيق JAVA الخاص بك.
يبدو النصر؟
ليس حقا كان الحيرة الطفيفة ناجمة عن التأخير المؤقت أو ، بشكل علمي ، التأخر. في البداية يكون هذا مقبولًا بشكل أو بآخر ، ولكن إذا كان لديك الصبر لمشاهدة الفيديو حتى النهاية ، فسترى أن التأخير بنهاية الدقيقة الأولى من البث يصل إلى خمس ثوانٍ. كان لدي ما يكفي من الصبر لمدة 10 دقائق من إطلاق النار ، لكن الغريب أن التأخير لم يزد بعد ، لكنه ظل في نفس الحدود.
بالطبع ، لمشاهدة فيديو من الكاميرا ، هذا سوف يحدث ، لكن بالكاد يتحكم في روبوت. حتى روفر القمر كان رد فعل مرتين أسرع!
سقطت الشكوك على الفور في عمليات التخزين المؤقت ، واتضح أنها (الشكوك) صحيحة.
وكان الأكثر غطرسة:
caching for network resources
إنه يأكل كل شيء تقريبًا افتراضيًا ، إذا لم يتم إعطاؤه له في الوقت المحدد.
يمكن ترتيب تأخر و:
caching for cameras and microphones
لذلك ، لتجنب التأخير متعدد الثواني ، يوصى بإضافة الأسطر التالية إلى نفس صفيف السلسلة ، مفصولة بفواصل:
"--live-caching=100", "--network-caching=500",
يتم تعيين المعلمات هناك بالميلي ثانية وبالتالي يمكن لأي شخص اختيارها لأنفسهم.
يمكنك أيضًا استخدام المفتاح:
"--clock-jitter=time in milliseconds",
ثم سيحاول مشغل الوسائط تحسين الارتعاش - ارتعاش الشاشة. ولكن هناك ، كلما تم ضبط المزيد من الوقت ، كان ذلك أفضل ، وهذا أمر مفهوم. لذلك يبقى فقط السعي للتوصل إلى إجماع وأحيانًا رؤية مثل هذا العار في السجلات:

لقد أراد ، كما تعلمون ، إصلاح الارتعاش وتحديد الفاصل الزمني صغير جدًا. الآن هو خطأي.
الآن يبدو أن كل شيء كما ينبغي. تم تقليل التأخير إلى أقل من ثانية واحدة (على الرغم من أنه أقل بقليل).
نتيجة لذلك ، حصلنا على رمز عمل صغير جدًا import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import uk.co.caprica.vlcj.discovery.NativeDiscovery; import uk.co.caprica.vlcj.player.MediaPlayerFactory; import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer; import uk.co.caprica.vlcj.player.embedded.videosurface.CanvasVideoSurface; public class BasicVideoPlayer { public final JFrame frame; public static String mrl; public static MediaPlayerFactory mpf; public static EmbeddedMediaPlayer MediaPlayer; public static CanvasVideoSurface videoSurface; public static Canvas canvas; public static void main(final String[] args) { new NativeDiscovery().discover(); mrl = "udp://@:40002"; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { BasicVideoPlayer vp = new BasicVideoPlayer(); vp.start(mrl); } }); } public BasicVideoPlayer() { frame = new JFrame("My First Media Player"); frame.setBounds(200,100, 540, 340); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.out.println(e); MediaPlayer.release(); mpf.release(); System.exit(0); } }); JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); canvas = new Canvas(); String[] args = { "--video-filter", "rotate", "--rotate-angle", "270", "--demux=h264", "--clock-jitter=100", "--live-caching=100", "--network-caching=500", }; mpf = new MediaPlayerFactory(args); videoSurface = mpf.newVideoSurface(canvas); MediaPlayer = mpf.newEmbeddedMediaPlayer(); MediaPlayer.setVideoSurface(videoSurface); contentPane.add(canvas, BorderLayout.CENTER); frame.setContentPane(contentPane); frame.setVisible(true); } public void start(String mrl) { MediaPlayer.playMedia(mrl); } }
يمكنك الآن دمج بث الفيديو في برنامج التحكم الآلي الخاص بي ، حيث اعتدت نقل الفيديو على شكل قطع. ويجب أن أقول أن الكود قد تم تبسيطه إلى حد كبير ، وأن الجودة قد تحسنت بدرجة كبيرة. بالإضافة إلى كل شيء إلى دفق الفيديو ، يمكننا نقل القراءات
التسارع
الجيروسكوبات
مستوى الإضاءة
ضغط الهواء
قراءات البوصلة
درجة الحرارة
وحتى الرطوبة
شريطة ، بالطبع ، أن كل هذه المجسات متوفرة على هاتفك الذكي.
وحتى تشغيل كشافات! تلقائيا! إذا انخفض مستوى الإضاءة.
لا يكاد أي شخص مهتمًا بشكل خاص ، ولكن في حالة وجود رابط إلى github:
للعربةللهاتف الذكي