مميزEngineeringDone

Docker-with-WebCam — الوصول إلى كاميرا المضيف من داخل حاوية Docker

مستودع يوضّح كيف تصل حاوية Docker إلى كاميرا المضيف عبر بثّ FFmpeg بصيغة mpegts فوق UDP بدلاً من تمرير الجهاز مباشرة، مع مثال التقاط بلغة Python و OpenCV.

٢٢ يوليو ٢٠٢٦
4 التقنيات
English
Docker-with-WebCam — الوصول إلى كاميرا المضيف من داخل حاوية Docker

عن هذا المشروع

دليل عملي لتمرير كاميرا الويب من نظام المضيف إلى داخل حاوية Docker عبر بثّ FFmpeg على UDP، مع مثال التقاط ومعالجة بلغة Python باستخدام OpenCV.

التقنيات

DockerPythonOpenCVLinux

i99dev_project_docker-webcam_cover_1200x630_v1.0.0.svg

مستودع أدوات عملي — الهدف منه توثيق طريقة تشغيل كاميرا الويب داخل حاوية Docker على أنظمة تشغيل مختلفة، بعد أن ظهرت الحاجة إليها في مشروع رؤية حاسوبية.

نظرة عامة

Docker-with-WebCam ليس مكتبة ولا إطار عمل، بل وصفة تشغيل موثّقة: كيف تحصل حاوية Docker على تدفّق فيديو حيّ من كاميرا متصلة بجهاز المضيف، ثم تعالجه بلغة Python عبر opencv-python.

الفكرة الأساسية بسيطة ومقصودة: بدلاً من محاولة تمرير جهاز الكاميرا نفسه إلى داخل الحاوية، يُحوَّل الفيديو إلى بثّ شبكي على المضيف، ثم تستهلكه الحاوية كأي مصدر شبكي آخر.

ffmpeg -f dshow -framerate 30 -i video="c922 Pro Stream Webcam" \
       -vcodec mpeg4 -q 12 -f mpegts udp://127.0.0.1:1235

المشكلة

الوصول إلى كاميرا من داخل حاوية يصطدم بثلاثة قيود حقيقية:

  1. العزل هو الغاية من الحاوية. الحاوية لا ترى /dev الخاص بالمضيف افتراضياً، وهذا سلوك مقصود لا خلل يُصلَح.
  2. الفروق بين أنظمة التشغيل. على Linux يمكن نظرياً تمرير /dev/video0، لكن هذا الحلّ لا وجود له أصلاً على Windows أو macOS حيث تدير النواة الأجهزة بطريقة مختلفة تماماً.
  3. عرض النتيجة. حتى بعد التقاط الإطارات، فإن نافذة cv2.imshow تحتاج خادم عرض؛ والحاوية لا تملك واحداً.

التخطيط

قُسّم العمل إلى ثلاث قطع مستقلة، كل واحدة قابلة للاختبار وحدها قبل وصلها بغيرها:

القطعة مكانها مسؤوليتها
مصدر الفيديو المضيف قراءة الكاميرا وبثّها عبر FFmpeg
قناة النقل الشبكة نقل mpegts فوق UDP إلى منفذ محلي
المستهلك الحاوية فتح التدفّق بـ OpenCV ومعالجة الإطارات

هذا التقسيم يسمح بالتحقّق من البثّ بمشغّل فيديو عادي قبل بناء أي صورة Docker، وهو ما يختصر التشخيص لاحقاً إلى نصفين واضحين: هل المشكلة في المصدر أم في المستهلك؟

القرارات المعمارية

البثّ الشبكي بدلاً من تمرير الجهاز. الحل المباشر — --device=/dev/video0 — يعمل على Linux فقط ويربط الوصفة بنظام تشغيل واحد. تحويل الكاميرا إلى تدفّق UDP يجعل الحاوية تتعامل مع عنوان لا مع عتاد، فتصبح نفس صورة Docker صالحة على Windows و macOS و Linux دون تعديل.

mpegts فوق UDP لا TCP. الحاوية تقرأ فيديو حيّاً؛ الإطار المتأخّر لا قيمة له. UDP يُسقط ما يتأخّر بدل أن يعيد إرساله ويراكم التأخير، وmpegts تحتمل فقدان الحزم لأنها مصمَّمة للبثّ لا للتخزين. عامل الجودة -q 12 يوازن بين وضوح الصورة وحجم التدفّق على الشبكة المحلية.

تفويض العرض إلى خادم X على المضيف. بدل حشو الحاوية بمكدّس رسومي كامل، تُوجَّه نافذة العرض إلى خادم X خارجي: Xming على Windows وXQuartz على macOS. تبقى الصورة خفيفة، ويبقى العرض مسؤولية المضيف.

التنفيذ

التوثيق مُنظَّم كمسار لكل نظام تشغيل، لأن الخطوات تختلف فعلياً وليس شكلياً:

  • Windows — تثبيت Xming وتشغيله بخيار no access control، ثم إضافة ffmpeg إلى متغيّر Path. يُسرد العتاد المتاح أولاً بـ ffmpeg -list_devices true -f dshow -i dummy، ويُنسخ اسم الكاميرا حرفياً كما يظهر في المخرجات — وهو أكثر موضع يقع فيه الخطأ.
  • macOS — يعتمد على ffmpeg عبر brew وXQuartz للعرض، مع تنبيه صريح في التوثيق: الكاميرا المدمجة غير مدعومة، ويلزم استخدام كاميرا USB.
  • Linux — ما زال مفتوحاً في التوثيق ومُعلَّماً كعمل قيد الإنجاز.
  • الحاوية — سكربت python/main.py يفتح عنوان UDP مصدراً للفيديو عبر opencv-python ويعالج الإطارات كأنها قادمة من كاميرا محلية.

تهيئة الحاوية

لكي يصل التدفّق وتظهر النافذة، تحتاج الحاوية إلى فتح منفذ UDP ومعرفة عنوان خادم العرض على المضيف — عبر devcontainer في VS Code:

{
  "runArgs": ["-ti", "-p", "1235:1235/udp", "-e", "DISPLAY=<localhostIp>:0.0"]
}

أو مباشرة من سطر الأوامر:

docker run -ti -p 1235:1235/udp -e DISPLAY=<localhostIP>:0.0 vscode

والمهمّ هنا أن DISPLAY يأخذ عنوان المضيف على الشبكة لا localhost، وإلا لم تجد الحاوية خادم X.

أمّا صورة الحاوية فتحتاج مكتبات الترميز والرسوميات قبل بناء OpenCV — منها libavcodec-dev وlibswscale-dev وlibavformat-dev وحزم GStreamer وlibopencv-dev وqtbase5-dev وffmpeg وusbutils، وجميعها مجموعة في ملف .devcontainer/Dockerfile.

النتيجة والدروس

المستودع يقدّم مساراً يعمل من طرفه إلى طرفه على Windows و macOS، وحصد ⭐ 7 نجوم من مطوّرين واجهوا المشكلة نفسها.

  1. حوّل مشكلة العتاد إلى مشكلة شبكة. ما إن يصبح المصدر عنواناً بدل جهاز، حتى تختفي فروق أنظمة التشغيل من داخل الحاوية بالكامل.
  2. الاختلاف بين المنصّات جوهري لا تجميلي. dshow على Windows وavfoundation على macOS ليسا اسمين لشيء واحد؛ أي توثيق يتظاهر بأن الخطوات موحّدة سيفشل عند أول مستخدم.
  3. التوثيق الصادق أنفع من التوثيق الكامل. ترك مسار Linux مُعلَّماً كـ 🚧 أوضح للقارئ من إخفائه أو ملئه بخطوات غير مُجرَّبة.

الروابط

روابط المشروع

تاريخ البداية٢٢ يوليو ٢٠٢٦
الحالةDone

مشاركة المشروع