שידורים חיים שניתן להוסיף ל-MediaStreamTrack

התוכן של MediaStreamTrack חשוף כזרם שאפשר לשנות או להשתמש בו כדי ליצור תוכן חדש.

רקע

בהקשר של Media capture and Streams API, הממשק MediaStreamTrack מייצג טראק מדיה אחד בתוך שידור. בדרך כלל מדובר בטראקים של אודיו או של וידאו, אבל יכול להיות שקיימים סוגים נוספים של טראק. MediaStream אובייקטים מכילים אפס אובייקטים MediaStreamTrack או יותר, שמייצגים טראקים שונים של אודיו או וידאו. לכל MediaStreamTrack יכול להיות ערוץ אחד או יותר. הערוץ מייצג את היחידה הקטנה ביותר של שידור מדיה, למשל אות אודיו שמשויך לרמקול מסוים, למשל שמאל או ימין בטראק של אודיו בסטריאו.

מהם שידורי סטרימינג שניתנים להוספה עבור MediaStreamTrack?

הרעיון המרכזי בבסיס של שידורים שניתן להוסיף ל-MediaStreamTrack הוא לחשוף את התוכן של MediaStreamTrack כאוסף של סטרים (כפי שמוגדר על ידי Streams API של whatWG). אפשר לשנות את השידורים האלה כדי להוסיף רכיבים חדשים.

אם מעניקים למפתחים גישה לשידור הווידאו (או האודיו) ישירות, הם יכולים לבצע שינויים ישירות בשידור. לעומת זאת, כדי לממש את אותה משימה של מניפולציית וידאו בשיטות מסורתיות, המפתחים צריכים להשתמש במתווכים כמו <canvas>. (לפרטים על התהליך הזה, ראו, לדוגמה: video + Canvas = חוקית).

תמיכת דפדפן

קטעי סטרימינג שניתנים להוספה עבור MediaStreamTrack נתמכים מ-Chrome 94.

תרחישים לדוגמה

תרחישים לדוגמה עבור סטרימינג שניתן להוסיף עבור MediaStreamTrack כוללים, בין היתר:

  • גאדג'טים לשיחות ועידה בווידאו כמו 'כובעים מצחיקים' או רקעים וירטואליים.
  • עיבוד קולי, כמו מקודדים של תוכנות.

איך משתמשים בשידורים הניתנים להוספה עבור MediaStreamTrack

זיהוי תכונות

בהמשך מפורטים השידורים הניתנים להוספה באמצעות זיהוי תכונות עבור התמיכה ב-MediaStreamTrack.

if ('MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window) {
  // Insertable streams for `MediaStreamTrack` is supported.
}

מושגי ליבה

שידורים שאפשר להוסיף ל-MediaStreamTrack מבוססים על קונספטים שהוצעו בעבר על ידי WebCodecs, ומפצלים את MediaStreamTrack לשני רכיבים:

  • MediaStreamTrackProcessor, שצורך מקור של אובייקט MediaStreamTrack ויוצר זרם של פריימים של מדיה, באופן ספציפי VideoFrame או AudioFrame). זהו sink בטראק שמאפשר לחשוף את הפריימים הלא מקודדים מהטראק כ-ReadableStream.
  • MediaStreamTrackGenerator, שמנצל זרם של פריימים של מדיה וחושף ממשק MediaStreamTrack. אפשר לספק אותו לכל sink, בדיוק כמו טראק של getUserMedia(). הוא מקבל מסגרות מדיה כקלט.

MediaStreamTrackProcessor

אובייקט MediaStreamTrackProcessor חושף מאפיין אחד, readable. היא מאפשרת לקרוא את הפריימים מתוך MediaStreamTrack. אם הטראק הוא טראק של וידאו, מקטעים שנקראו מ-readable יהיו אובייקטים של VideoFrame. אם הטראק הוא טראק של אודיו, מקטעים שנקראו מ-readable יהיו אובייקטים של AudioFrame.

MediaStreamTrackGenerator

באופן דומה, אובייקט MediaStreamTrackGenerator חושף מאפיין אחד, writable, שהוא WritableStream שמאפשר לכתוב פריימים של מדיה ל-MediaStreamTrackGenerator, שהוא עצמו MediaStreamTrack. אם המאפיין kind הוא "audio", השידור מקבל AudioFrame אובייקטים וייכשל בכל סוג אחר. אם הסוג הוא "video", הזרם מקבל VideoFrame אובייקטים וייכשל בכל סוג אחר. כשפריים נכתבים ב-writable, השיטה close() של המסגרת מופעלת באופן אוטומטי, כך שמשאבי המדיה שלה לא נגישים יותר מ-JavaScript.

MediaStreamTrackGenerator הוא טראק שעבורו אפשר להטמיע מקור מותאם אישית על ידי כתיבת פריימים של מדיה לשדה writable.

סיכום של כל המידע

הרעיון המרכזי הוא ליצור שרשרת עיבוד באופן הבא:

מסלול פלטפורמה ← מעבד ← טרנספורמציה ← גנרטור ← כיורי פלטפורמה

הדוגמה הבאה ממחישה את השרשרת של אפליקציה לסריקת ברקודים, שמדגישה ברקוד שזוהה בווידאו בשידור חי.

const stream = await getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks()[0];

const trackProcessor = new MediaStreamTrackProcessor({ track: videoTrack });
const trackGenerator = new MediaStreamTrackGenerator({ kind: 'video' });

const transformer = new TransformStream({
  async transform(videoFrame, controller) {
    const barcodes = await detectBarcodes(videoFrame);
    const newFrame = highlightBarcodes(videoFrame, barcodes);
    videoFrame.close();
    controller.enqueue(newFrame);
  },
});

trackProcessor.readable.pipeThrough(transformer).pipeTo(trackGenerator.writable);

const videoBefore = document.getElementById('video-before');
const videoAfter = document.getElementById('video-after');
videoBefore.srcObject = stream;
const streamAfter = new MediaStream([trackGenerator]);
videoAfter.srcObject = streamAfter;

הדגמה (דמו)

ניתן לראות את ההדגמה של סורק קוד ה-QR מהקטע שלמעלה בפעולה בדפדפן במחשב או בנייד. כשמחזיקים קוד QR מול המצלמה, האפליקציה תזהה אותו ותדגיש אותו. קוד המקור של האפליקציה מופיע ב-Glitch.

סורק קודי QR שפועל בכרטיסייה של דפדפן במחשב ומציג קוד QR שזוהה ומודגש בטלפון שהמשתמש מחזיק מול המצלמה של המחשב הנייד.

שיקולי אבטחה ופרטיות

האבטחה של ה-API הזה תלויה במנגנונים הקיימים בפלטפורמת האינטרנט. כשנתונים נחשפים באמצעות הממשק VideoFrame ו-AudioFrame, חלים הכללים של הממשקים האלה לטיפול בנתונים שהושפעו מהמקור. לדוגמה, לא ניתן לגשת לנתונים ממשאבים ממקורות שונים בגלל המגבלות הקיימות על הגישה למשאבים האלה (למשל, אי אפשר לגשת לפיקסלים של תמונה או רכיב וידאו ממקורות שונים). בנוסף, הגישה לנתוני המדיה ממצלמות, ממיקרופונים או ממסכים כפופה לאישור המשתמשים. נתוני המדיה שה-API הזה חושף כבר זמינים דרך ממשקי API אחרים.

משוב

צוות Chromium רוצה לשמוע על החוויות שלך עם שידורים הניתנים להוספה עבור MediaStreamTrack.

לספר לנו על עיצוב ה-API

האם יש משהו ב-API שלא פועל כצפוי? או האם חסרים שיטות או מאפיינים שאתם צריכים ליישם את הרעיון? יש לכם שאלה או הערה לגבי מודל האבטחה? שלחו בעיה במפרט במאגר GitHub המתאים, או הוסיפו את דעתכם לבעיה קיימת.

דיווח על בעיה בהטמעה

האם מצאת באג בהטמעה של Chromium? או שההטמעה שונה מהמפרט? דווחו על באג בכתובת new.crbug.com. הקפידו לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור, והזינו Blink>MediaStream בתיבה רכיבים. גליץ' הוא כלי מעולה לשיתוף גיבויים מהירים וקלים.

הבעת תמיכה ב-API

האם בכוונתך להשתמש בשידורים שניתנים להוספה בשביל MediaStreamTrack? התמיכה הציבורית עוזרת לצוות Chromium לתעדף תכונות, ומוכיחה לספקי דפדפנים אחרים עד כמה חיונית התמיכה בהם.

שלח ציוץ אל @ChromiumDev באמצעות ה-hashtag #InsertableStreams וספר לנו איפה אתם משתמשים בו ואיך אתם משתמשים בו.

אישורים

השידורים הניתנים להוספה למפרט של MediaStreamTrack נכתבו על ידי הרלד Alvestrand ו-Guido Urdaneta. המאמר הזה נבדק על ידי הראלד אלווסטרנד, ג'ו מדלי, בן וגנר, Huib Kleinhout ו-פרנסואה בופורט. תמונה ראשית (Hero) של כריס מונטגומרי ב-UnFlood.