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

התוכן של MediaStreamTrack מוצג כסטרימינג שאפשר לערוך או להשתמש בו כדי ליצור תוכן חדש

רקע

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

מהם סטרימינגים שניתן להוסיף למינוי של MediaStreamTrack?

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

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

תמיכה בדפדפנים

התמיכה בזרמים שניתן להוסיף ל-MediaStreamTrack זמינה מגרסה 94 של Chrome.

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

תרחישי שימוש בזרמים שאפשר להוסיף להם נתונים ב-MediaStreamTrack כוללים, בין היתר:

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

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

זיהוי תכונות

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

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

מושגי ליבה

‫Insertable streams for MediaStreamTrack מבוסס על רעיונות שהוצעו בעבר על ידי WebCodecs, ומפצל את MediaStreamTrack לשני רכיבים:

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

MediaStreamTrackProcessor

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

MediaStreamTrackGenerator

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

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

סיכום

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

Platform Track → Processor → Transform → Generator → Platform Sinks

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

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 מול המצלמה והאפליקציה תזהה אותו ותדגיש אותו. אפשר לראות את קוד המקור של האפליקציה ב-GitHub.

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

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

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

משוב

צוות Chromium רוצה לשמוע על החוויות שלכם עם הזרמות שאפשר להוסיף ל-MediaStreamTrack.

נשמח לקבל מידע על עיצוב ה-API

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

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

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

תמיכה ב-API

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

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

תודות

המפרט של הזרמים שאפשר להוסיף ל-MediaStreamTrack נכתב על ידי Harald Alvestrand ו-Guido Urdaneta. המאמר הזה נבדק על ידי Harald Alvestrand,‏ Joe Medley,‏ Ben Wagner,‏ Huib Kleinhout וFrançois Beaufort. תמונה ראשית (Hero) מאת Chris Montgomery ב-Unsplash.