التقاط الصوت والفيديو بتنسيق HTML5

مقدمة

لطالما كان التقاط الصوت والفيديو "الفكرة الرئيسية" في تطوير الويب منذ فترة طويلة. اضطررنا لسنوات عديدة إلى الاعتماد على المكونات الإضافية للمتصفح (فلاش أو Silverlight) لإنجاز هذه المهمة. بإمكانك الآن:

HTML5 لإيجاد الحل. قد لا يكون ذلك واضحًا، لكن ظهور HTML5 أدى إلى زيادة كبيرة في الوصول إلى أجهزة الأجهزة. من الأمثلة الجيدة على استخدام رصد الموقع الجغرافي (نظام تحديد المواقع العالمي) وواجهة برمجة تطبيقات الاتجاه (مقياس التسارع) وWebGL (وحدة معالجة الرسومات) وWeb Audio API (الأجهزة الصوتية). هذه الميزات قوية للغاية، وتكشف عن واجهات برمجة تطبيقات JavaScript عالية المستوى التي تضع فوق إمكانات الأجهزة الأساسية للنظام.

يقدم هذا البرنامج التعليمي واجهة برمجة تطبيقات جديدة، وهي GetUserMedia، تسمح لتطبيقات الويب بالوصول إلى كاميرا المستخدم والميكروفون.

الطريق إلى getUserMedia()

إذا لم تكن تعرف تاريخ هذه الواجهة، يمكنك الاستعانة بواجهة برمجة تطبيقات getUserMedia() كقصة مشوّقة.

تطوّرت العديد من أنواع واجهات برمجة تطبيقات التقاط الوسائط خلال السنوات القليلة الماضية. أدرك العديد من الأشخاص الحاجة إلى إمكانية الوصول إلى الأجهزة الأصلية على الويب، ولكن هذا دفع الجميع وأمهم إلى وضع مواصفات جديدة، فأصبحت الأمور فوضوية لدرجة أن W3C قررت أخيرًا تشكيل مجموعة عمل. الغرض الوحيد منه؟ هل تفهم الجنون؟ تم تكليف مجموعة عمل سياسة واجهات برمجة التطبيقات للأجهزة (DAP) بدمج مجموعة كبيرة من الاقتراحات وتوحيدها.

سأحاول تلخيص ما حدث في عام 2011...

الجولة 1: التقاط وسائط HTML

كانت HTML Media التقاط الوسائط هي أول خطوة قامت بها وحدة إدارة البيانات (DAP) في توحيد عملية التقاط الوسائط على الويب. وهي تعمل عن طريق زيادة تحميل <input type="file"> وإضافة قيم جديدة للمَعلمة accept.

إذا أردت السماح للمستخدمين بأخذ لقطة لأنفسهم باستخدام كاميرا الويب، يمكنك استخدام capture=camera:

<input type="file" accept="image/*;capture=camera">

في ما يلي الخطوات التي يجب اتّباعها لتسجيل فيديو أو محتوى صوتي:

<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">

هذا رائع، أليس كذلك؟ أحب بشكل خاص أن يقوم بإعادة استخدام إدخال ملف. من الناحية الدلالية، هذا منطقي جدًا. وتقتصر إمكانية استخدام "واجهة برمجة التطبيقات" هذه تحديدًا على إمكانية تنفيذ تأثيرات في الوقت الفعلي (على سبيل المثال، عرض بيانات كاميرا الويب المباشرة على <canvas> وتطبيق فلاتر WebGL). يتيح لك برنامج HTML Media التقاط ملف وسائط أو أخذ لقطة في الوقت المناسب فقط.

الدعم:

  • متصفح Android 3.0 - أحد عمليات التنفيذ الأولى. يمكنك مشاهدة هذا الفيديو للاطّلاع على أمثلة واقعية.
  • Chrome لنظام Android (0.16)
  • Firefox Mobile 10.0
  • iOS6 Safari وChrome (دعم جزئي)

الجولة 2: عنصر الجهاز

اعتقد الكثيرون أن ميزة HTML Media Record كانت محدودة للغاية، لذا ظهرت مواصفة جديدة تتوافق مع أي نوع من الأجهزة (المستقبلية). ومن غير المستغرب أنّ التصميم دعا إلى توفّر عنصر جديد، وهو العنصر <device>، الذي أصبح سابقًا لـ getUserMedia().

كان Opera من أوائل المتصفحات التي أنشأت عمليات تنفيذ مبدئية لتسجيل الفيديو استنادًا إلى العنصر <device>. بعد وقت قصير (في اليوم نفسه على وجه التحديد)، قرر فريق WhatWG إزالة العلامة <device> لصالح مستخدم آخر، وهذه المرة عبارة عن واجهة برمجة تطبيقات JavaScript تُسمىnavigator.getUserMedia(). بعد أسبوع، طرحت Opera إصدارات جديدة تضمّنت توافقًا مع مواصفات getUserMedia() المعدَّلة. وفي وقت لاحق من ذلك العام، انضمت Microsoft إلى هذه الإصدارات من خلال طرح Lab for IE9 لتوافق مع المواصفات الجديدة.

إليك الشكل الذي كان يتم اعتباره <device>:

<device type="media" onchange="update(this.data)"></device>
<video autoplay></video>
<script>
  function update(stream) {
    document.querySelector('video').src = stream.url;
  }
</script>

الدعم:

لم يتضمّن أي متصفّح تم إصداره <device>. إلا أنّ واجهة برمجة التطبيقات <device> كانت تتضمّن شيئين رائعين، هما: 1.) كانت دلالية، و2.) كانت قابلة للتوسّع بسهولة لتتوافق مع الأجهزة الأخرى بالإضافة إلى أجهزة الصوت/الفيديو.

خذ نفسًا. تتحرّك هذه العناصر بسرعة.

الجولة 3: WebRTC

سار العنصر <device> في نهاية المطاف أمام كائن Dodo.

تم تسريع عملية العثور على واجهة برمجة تطبيقات التقاط مناسبة بفضل الجهود الكبيرة التي تفرضها WebRTC (اتصالات الويب في الوقت الفعلي). تشرف مجموعة عمل W3C WebRTC على هذه المواصفات. هناك عمليات تنفيذ لدى Google وOpera وMozilla وبعض التطبيقات الأخرى.

ويرتبط getUserMedia() بخدمة WebRTC، لأنّها بوابة الدخول إلى مجموعة واجهات برمجة التطبيقات هذه. وهي توفّر الوسائل اللازمة للوصول إلى بث الكاميرا/الميكروفون على الجهاز الخاص بالمستخدم.

الدعم:

يمكنك استخدام getUserMedia() منذ إصدارات Chrome 21 وOpera 18 وFirefox 17.

الخطوات الأولى

باستخدام navigator.mediaDevices.getUserMedia()، يمكننا أخيرًا الوصول إلى كاميرا الويب والميكروفون بدون مكوّن إضافي. يمكنك الآن الوصول إلى الكاميرا من خلال إجراء مكالمة، وليس التثبيت. ويتم إدخاله في المتصفح مباشرةً. هل أنت متحمس بعد؟

رصد الميزات

يعد اكتشاف الميزات تحققًا بسيطًا من وجود navigator.mediaDevices.getUserMedia:

if (navigator.mediaDevices?.getUserMedia) {
  // Good to go!
} else {
  alert("navigator.mediaDevices.getUserMedia() is not supported");
}

الحصول على إمكانية الوصول إلى جهاز إدخال

لاستخدام كاميرا الويب أو الميكروفون، عليك طلب الإذن. إنّ المَعلمة الأولى للسمة navigator.mediaDevices.getUserMedia() هي كائن يحدّد تفاصيل ومتطلبات كل نوع من الوسائط التي تريد الوصول إليها. على سبيل المثال، إذا كنت تريد الوصول إلى كاميرا الويب، يجب أن تكون المَعلمة الأولى هي {video: true}. لاستخدام كل من الميكروفون والكاميرا، مرر {video: true, audio: true}:

<video autoplay></video>

<script>
  navigator.mediaDevices
    .getUserMedia({ video: true, audio: true })
    .then((localMediaStream) => {
      const video = document.querySelector("video");
      video.srcObject = localMediaStream;
    })
    .catch((error) => {
      console.log("Rejected!", error);
    });
</script>

موافق. إذًا ما الذي يحدث هنا؟ يعد التقاط الوسائط مثالاً رائعًا على واجهات برمجة تطبيقات HTML5 الجديدة التي تعمل معًا. وهو يعمل مع رفقاء HTML5 الآخرين، <audio> و<video>. يُرجى العِلم أنّنا لا نضبط سمة src أو ندرج عناصر <source> في العنصر <video>. وبدلاً من إرسال عنوان URL للفيديو إلى ملف وسائط، سنضبط السمة srcObject على العنصر LocalMediaStream الذي يمثّل كاميرا الويب.

أطلب أيضًا من <video> إلى autoplay، وإلا سيتم تجميد الإطار الأول. تعمل إضافة "controls" أيضًا على النحو المتوقَّع.

ضبط قيود الوسائط (درجة الدقة والارتفاع والعرض)

يمكن أيضًا استخدام المَعلمة الأولى للسمة getUserMedia() لتحديد المزيد من المتطلبات (أو القيود) على بث الوسائط التي يتم عرضها. على سبيل المثال، بدلاً من الإشارة فقط إلى أنّك تريد الوصول الأساسي إلى الفيديو (مثل {video: true})، يمكنك أيضًا اشتراط أن يكون البث بدقة عالية:

const hdConstraints = {
  video: { width: { exact:  1280} , height: { exact: 720 } },
};

const stream = await navigator.mediaDevices.getUserMedia(hdConstraints);
const vgaConstraints = {
  video: { width: { exact:  640} , height: { exact: 360 } },
};

const stream = await navigator.mediaDevices.getUserMedia(hdConstraints);

لمزيد من الإعدادات، يمكنك الاطّلاع على Restrictts API.

اختيار مصدر وسائط

تطلب الطريقة enumerateDevices() في الواجهة MediaDevices قائمة بأجهزة إدخال الوسائط وإخراجها المتاحة، مثل الميكروفونات والكاميرات وسماعات الرأس وما إلى ذلك. يتم حلّ الوعد الذي تم إرجاعه باستخدام مصفوفة من عناصر MediaDeviceInfo تصف الأجهزة.

في هذا المثال، يتم تحديد آخر ميكروفون وكاميرا تم العثور عليهما كمصدرَين لبث الوسائط:

if (!navigator.mediaDevices?.enumerateDevices) {
  console.log("enumerateDevices() not supported.");
} else {
  // List cameras and microphones.
  navigator.mediaDevices
    .enumerateDevices()
    .then((devices) => {
      let audioSource = null;
      let videoSource = null;

      devices.forEach((device) => {
        if (device.kind === "audioinput") {
          audioSource = device.deviceId;
        } else if (device.kind === "videoinput") {
          videoSource = device.deviceId;
        }
      });
      sourceSelected(audioSource, videoSource);
    })
    .catch((err) => {
      console.error(`${err.name}: ${err.message}`);
    });
}

async function sourceSelected(audioSource, videoSource) {
  const constraints = {
    audio: { deviceId: audioSource },
    video: { deviceId: videoSource },
  };
  const stream = await navigator.mediaDevices.getUserMedia(constraints);
}

راجع العرض التوضيحي الرائع لسام دوتون حول كيفية السماح للمستخدمين باختيار مصدر الوسائط.

الأمان

تعرض المتصفّحات مربّع حوار الأذونات عند طلب الاتصال بـ navigator.mediaDevices.getUserMedia()، ما يتيح للمستخدمين خيار منح إذن الوصول إلى الكاميرا أو الميكروفون أو رفضه. على سبيل المثال، إليك مربّع حوار أذونات Chrome:

مربّع حوار الأذونات في Chrome
مربع حوار الأذونات في Chrome

توفير العنصر الاحتياطي

بالنسبة إلى المستخدمين الذين لا يمكنهم استخدام navigator.mediaDevices.getUserMedia()، أحد الخيارات المتاحة هو الرجوع إلى ملف فيديو حالي إذا كانت واجهة برمجة التطبيقات غير متوافقة و/أو تعذّر الاتصال لسبب ما:

if (!navigator.mediaDevices?.getUserMedia) {
  video.src = "fallbackvideo.webm";
} else {
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  video.srcObject = stream;
}