يمكن الآن للعديد من المتصفّحات الوصول إلى إدخال الفيديو والصوت من العميل. ومع ذلك، استنادًا إلى المتصفّح، قد تكون تجربة كاملة ديناميكية ومضمّنة ، أو قد يتم تفويضها إلى تطبيق آخر على جهاز المستخدم.
البدء بخطوات بسيطة وبشكل تدريجي
إنّ أسهل طريقة لحلّ هذه المشكلة هي أن تطلب من المستخدم تقديم ملف مسجّل مسبقًا. يمكنك إجراء ذلك من خلال إنشاء عنصر بسيط لinputملف وإضافة فلتر accept
يشير إلى أنّه يمكننا قبول ملفات الفيديو فقط وcapture
سمة تشير إلى أنّنا نريد الحصول عليها مباشرةً من الكاميرا.
<input type="file" accept="video/*" capture />
تعمل هذه الطريقة على جميع المنصات. على الكمبيوتر المكتبي، سيُطلب من المستخدم تحميل ملف من
نظام الملفات (مع تجاهل السمة capture
). في Safari
على نظام التشغيل iOS، سيتم فتح تطبيق الكاميرا، ما يتيح لك تسجيل فيديو ثم إعادة إرساله إلى صفحة الويب. أما على Android، فسيمنح المستخدم خيار تحديد التطبيق الذي سيتم تسجيل الفيديو فيه قبل إرساله مرة أخرى إلى صفحة الويب.
تحتوي العديد من الأجهزة الجوّالة على أكثر من كاميرا واحدة. إذا كان لديك إعداد مفضّل، يمكنك ضبط السمة capture
على user
إذا كنت تريد أن تكون الكاميرا مواجهة للمستخدم، أو environment
إذا كنت تريد أن تكون
الكاميرا مواجهة للخارج.
<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />
يُرجى العِلم أنّ هذه مجرد إرشادات، وإذا لم يتيح المتصفّح الخيار أو لم يكن نوع الكاميرا الذي طلبته متاحًا، قد يختار المتصفّح كاميرا أخرى.
بعد انتهاء المستخدم من التسجيل وعودته إلى الموقع الإلكتروني،
عليك الحصول على بيانات الملف بطريقة ما. يمكنك الوصول بسرعة من خلال
ربط حدث onchange
بعنصر الإدخال ثم قراءة
السمة files
لعنصر الحدث.
<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
var recorder = document.getElementById('recorder');
var player = document.getElementById('player');
recorder.addEventListener('change', function (e) {
var file = e.target.files[0];
// Do something with the video file.
player.src = URL.createObjectURL(file);
});
</script>
بعد الحصول على إذن الوصول إلى الملف، يمكنك إجراء أي إجراء تريده عليه. على سبيل المثال، يمكنك إجراء ما يلي:
- إرفاقه مباشرةً بعنصر
<video>
حتى تتمكّن من تشغيله - تنزيل التطبيق على جهاز المستخدم
- حمِّله على خادم من خلال إرفاقه بـ
XMLHttpRequest
. - رسم الإطارات في لوحة وتطبيق فلاتر عليها
على الرغم من أنّ استخدام طريقة عنصر الإدخال للوصول إلى بيانات الفيديو هو شائع، إلا أنّه الخيار الأقل جاذبية. نريد الوصول إلى الكاميرا وتقديم تجربة رائعة في الصفحة مباشرةً.
الوصول إلى الكاميرا بشكل تفاعلي
يمكن للمتصفّحات الحديثة الوصول مباشرةً إلى الكاميرا، ما يتيح لنا إنشاء تجربتَين مدمجتَين بالكامل مع صفحة الويب ولن يضطر المستخدم أبدًا إلى مغادرة المتصفّح.
الحصول على إذن الوصول إلى الكاميرا
يمكننا الوصول إلى الكاميرا مباشرةً باستخدام واجهة برمجة تطبيقات في مواصفات WebRTC
المُسمّاة getUserMedia()
. سيطلب تطبيق getUserMedia()
من المستخدم منح الإذن بالوصول إلى كاميراته وميكروفوناته المتصلة.
في حال نجاح العملية، ستعرض واجهة برمجة التطبيقات Stream
يحتوي على البيانات من الكاميرا أو
الميكروفون، ويمكننا بعد ذلك إرفاقه بعنصر <video>
أو إرفاقه ببث WebRTC
أو حفظه باستخدام واجهة برمجة التطبيقات MediaRecorder
.
للحصول على البيانات من الكاميرا، ما عليك سوى ضبط video: true
في قيد
العنصر الذي يتم تمريره إلى واجهة برمجة التطبيقات getUserMedia()
.
<video id="player" controls></video>
<script>
var player = document.getElementById('player');
var handleSuccess = function (stream) {
player.srcObject = stream;
};
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then(handleSuccess);
</script>
إذا كنت تريد اختيار كاميرا معيّنة، يمكنك أولاً سرد الكاميرات المتاحة.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'videoinput');
});
يمكنك بعد ذلك تمرير معرّف الجهاز الذي تريد استخدامه عند الاتصال برقم getUserMedia
.
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
deviceId: devices[0].deviceId,
},
});
لا يُعدّ هذا الإجراء مفيدًا بحد ذاته. كل ما يمكننا فعله هو أخذ بيانات الفيديو وإعادة تشغيلها.
الوصول إلى البيانات الأولية من الكاميرا
للوصول إلى بيانات الفيديو الأوّلية من الكاميرا، يمكنك رسم كل إطار في <canvas>
و
التلاعب بالبكسل مباشرةً.
بالنسبة إلى لوحة الرسم ثنائية الأبعاد، يمكنك استخدام طريقة drawImage
للسياق لرسم الإطار الحالي لعنصر
<video>
في اللوحة.
context.drawImage(myVideoElement, 0, 0);
باستخدام لوحة WebGL، يمكنك استخدام عنصر <video>
كمصدر لملمس.
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
myVideoElement,
);
يُرجى العِلم أنّه في كلتا الحالتَين، سيتم استخدام الإطار الحالي للفيديو الذي يتم تشغيله. لمعالجة عدة لقطات، عليك إعادة رسم الفيديو على اللوحة في كل مرة.
يمكنك الاطّلاع على مزيد من المعلومات حول هذا الموضوع في مقالتنا حول تطبيق تأثيرات في الوقت الفعلي على الصور والفيديوهات.
حفظ البيانات من الكاميرا
إنّ أسهل طريقة لحفظ البيانات من الكاميرا هي استخدام واجهة برمجة التطبيقات
MediaRecorder
.
ستستخدِم واجهة برمجة التطبيقات MediaRecorder
مصدر البيانات الذي أنشأه getUserMedia
ثم تحفظ
البيانات تدريجيًا من مصدر البيانات في الوجهة المفضّلة لديك.
<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
let shouldStop = false;
let stopped = false;
const downloadLink = document.getElementById('download');
const stopButton = document.getElementById('stop');
stopButton.addEventListener('click', function() {
shouldStop = true;
})
var handleSuccess = function(stream) {
const options = {mimeType: 'video/webm'};
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.addEventListener('dataavailable', function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
if(shouldStop === true && stopped === false) {
mediaRecorder.stop();
stopped = true;
}
});
mediaRecorder.addEventListener('stop', function() {
downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
downloadLink.download = 'acetest.webm';
});
mediaRecorder.start();
};
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(handleSuccess);
</script>
في حالتنا، نحفظ البيانات مباشرةً في صفيف يمكننا تحويله لاحقًا إلى Blob
يمكن استخدامه بعد ذلك لحفظه على خادم الويب أو في ملف تخزين على جهاز المستخدم مباشرةً.
طلب الإذن لاستخدام الكاميرا بمسؤولية
إذا لم يمنح المستخدم موقعك الإلكتروني الإذن بالوصول إلى الكاميرا في السابق، عند getUserMedia
، سيطلب المتصفّح من المستخدم منح موقعك الإلكتروني الإذن بالوصول إلى الكاميرا.
يكره المستخدمون تلقّي إشعارات لطلب الوصول إلى الأجهزة القوية على أجهزتهم، وغالبًا ما سيحظرون الطلب أو سيتجاهلونه إذا لم يكن لديهم فهم لسياق إنشاء الإشعار. من أفضل الممارسات عدم طلب الوصول إلى الكاميرا إلا عند الحاجة الأولى. بعد أن يمنح المستخدم الإذن بالوصول، لن يُطلب منه ذلك مرة أخرى. وفي حال رفضه، لن تتمكّن من الوصول مرة أخرى لطلب الإذن منه.
استخدام Permissions API للتحقّق مما إذا كان لديك إذن الوصول
لا تمنحك واجهة برمجة التطبيقات getUserMedia
أي معلومات حول ما إذا كان لديك إذن بالوصول إلى الكاميرا. يتسبب ذلك في مشكلة، فلتقديم واجهة مستخدم رائعة
لحث المستخدم على منحك إذن الوصول إلى الكاميرا، عليك طلب
إذن الوصول إلى الكاميرا.
يمكن حلّ هذه المشكلة في بعض المتصفّحات باستخدام واجهة برمجة التطبيقات Permission API. تتيح لك واجهة برمجة التطبيقات
navigator.permission
طلب معلومات عن حالة إمكانية
الوصول إلى واجهات برمجة تطبيقات معيّنة بدون الحاجة إلى طلب الإذن مرة أخرى.
لمعرفة ما إذا كان بإمكانك الوصول إلى كاميرا المستخدم، يمكنك إدخال
{name: 'camera'}
في طريقة طلب البحث، وسيؤدي ذلك إلى عرض أيّ مما يلي:
granted
- إذا منحك المستخدم الإذن بالوصول إلى الكاميرا في السابقprompt
- لم يمنحك المستخدم إذن الوصول، وسيتم سؤاله عند الاتصال بالرقمgetUserMedia
.denied
- حظر النظام أو المستخدم الوصول إلى الكاميرة صراحةً، ولن تتمكّن من الوصول إليها.
ويمكنك الآن التحقّق سريعًا لمعرفة ما إذا كنت بحاجة إلى تغيير واجهة مستخدمك لتتلاءم مع الإجراءات التي يحتاج المستخدم إلى اتّخاذها.
navigator.permissions.query({name: 'camera'}).then(function (result) {
if (result.state == 'granted') {
} else if (result.state == 'prompt') {
} else if (result.state == 'denied') {
}
result.onchange = function () {};
});