يمكن الآن للعديد من المتصفّحات الوصول إلى إدخال الفيديو والصوت من العميل. ومع ذلك، استنادًا إلى المتصفّح، قد تكون تجربة كاملة ديناميكية ومضمّنة ، أو قد يتم تفويضها إلى تطبيق آخر على جهاز المستخدم.
البدء بخطوات بسيطة وبشكل تدريجي
أسهل شيء يمكنك القيام به هو أن تطلب من المستخدم تقديم ملف مسجل مسبقًا. يمكنك إجراء ذلك من خلال إنشاء عنصر بسيط ل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
API معرفة ما إذا كان بإمكانك الوصول إلى الكاميرا. يتسبب ذلك في مشكلة، فلتقديم واجهة مستخدم رائعة
لحث المستخدم على منحك إذن الوصول إلى الكاميرا، عليك طلب
إذن الوصول إلى الكاميرا.
يمكن حلّ هذه المشكلة في بعض المتصفّحات باستخدام واجهة برمجة التطبيقات 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 () {};
});