גלילה בכרטיסייה מוקלטת ושינוי מרחק התצוגה שלה

François Beaufort
François Beaufort

כבר אפשר לשתף כרטיסיות, חלונות ומסכים בפלטפורמת האינטרנט באמצעות Screen Capture API. כשאפליקציית אינטרנט קוראת ל-getDisplayMedia(), Chrome מציגה למשתמש בקשה לשתף כרטיסייה, חלון או מסך עם אפליקציית האינטרנט כסרטון MediaStreamTrack.

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

במסמך הזה נסביר על Captured Surface Control API החדש ב-Chrome, שמאפשר לאפליקציית האינטרנט לגלול בכרטיסייה שצולמה, וגם לקרוא ולכתוב את רמת הזום של כרטיסייה שצולמה.

משתמש גולל בכרטיסייה שצולמה ומגדיל את התצוגה שלה (הדגמה).

למה כדאי להשתמש ב-Captured Surface Control?

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

  • המשתמש לא יכול לראות את האפליקציה שצולמה ואת פידים הווידאו של משתמשים מרוחקים בו-זמנית, אלא אם הוא משתמש בתמונה בתוך תמונה או בחלונות נפרדים זה לצד זה לכרטיסייה של שיתוף המסך ולכרטיסייה של שיתוף המסך. במסך קטן יותר, יכול להיות שיהיה קשה לעשות זאת.
  • המשתמש צריך לעבור בין אפליקציית שיחות הווידאו לבין המשטח המצולם.
  • המשתמש מאבד את הגישה לפקדים שמוצגים באפליקציית הווידאו ועכשיו הוא לא נמצא בה, למשל: אפליקציית צ'אט מוטמעת, תגובות באמוג'י, התראות על משתמשים שמבקשים להצטרף לשיחה, פקדים של מולטימדיה ופריסה ותכונות שימושיות אחרות של שיתוף וידאו.
  • המגיש/ה לא יכול/ה להעביר את השליטה למשתתפים מרחוק. המצב הזה מוביל לתרחיש המוכר כל כך, שבו משתמשים מרחוק מבקשים מהמנחה לשנות את השקופית, לגלול מעט למעלה ולמטה או לשנות את מרחק התצוגה.

ממשק ה-API לניהול משטחים שתועדו פותר את הבעיות האלה.

איך משתמשים ב'שליטה בשטח התצוגה שצולם'?

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

איך מצלמים כרטיסייה בדפדפן

בשלב הראשון, מבקשים מהמשתמש לבחור משטח לשיתוף באמצעות getDisplayMedia(), ובמהלך התהליך משייכים אובייקט CaptureController לסשן הצילום. בקרוב נשתמש באובייקט הזה כדי לשלוט בשטח המצולם.

const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });

בשלב הבא, יוצרים תצוגה מקדימה מקומית של פני השטח שצולמו, בצורת רכיב <video>:

const previewTile = document.querySelector('video');
previewTile.srcObject = stream;

אם המשתמש יבחר לשתף חלון או מסך, זה לא יהיה בטווח האפשרויות שלנו כרגע – אבל אם הוא יבחר לשתף כרטיסייה, נוכל להמשיך.

const [track] = stream.getVideoTracks();

if (track.getSettings().displaySurface !== 'browser') {
  // Bail out early if the user didn't pick a tab.
  return;
}

בקשת הרשאה

ההפעלה הראשונה של forwardWheel(), ‏ increaseZoomLevel(), ‏ decreaseZoomLevel() או resetZoomLevel() באובייקט CaptureController נתון מובילה להצגת בקשה להרשאה. אם המשתמש מעניק הרשאה, ניתן להפעיל את השיטות האלה שוב.

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

גלילה

באמצעות forwardWheel(), אפליקציית הצילום יכולה להעביר אירועי גלילה מרכיב מקור באפליקציית הצילום עצמה למסך של הכרטיסייה שצולמה. לאפליקציה שצילמה את האירועים האלה אין אפשרות להבדיל ביניהם לבין אינטראקציה ישירה של משתמש.

בהנחה שאפליקציית הצילום משתמשת ברכיב <video> שנקרא "previewTile", הקוד הבא מראה איך להעביר אירועי שליחת גלגל לכרטיסייה שצולמה:

const previewTile = document.querySelector('video');
try {
  // Relay the user's action to the captured tab.
  await controller.forwardWheel(previewTile);
} catch (error) {
  // Inspect the error.
  // ...
}

ל-method forwardWheel() יש קלט יחיד שיכול להיות אחד מהערכים הבאים:

  • רכיב HTML שממנו אירועי גלילה יועברו לכרטיסייה שצולמה.
  • null, כדי לציין שההעברה צריכה להיפסק.

קריאה מוצלחת ל-forwardWheel() מבטלת את הקריאות הקודמות.

ההבטחה שמוחזרת על ידי forwardWheel() יכולה להידחות במקרים הבאים:

  • אם סשן הצילום עדיין לא התחיל או שכבר הופסק.
  • אם המשתמש לא העניק את ההרשאה הרלוונטית.

שינוי מרחק התצוגה

האינטראקציה עם רמת הזום של הכרטיסייה שצולמה מתבצעת באמצעות ממשקי ה-API הבאים של CaptureController:

getSupportedZoomLevels()

השיטה הזו מחזירה רשימה של רמות זום שנתמכות בדפדפן לסוג פני השטח שרוצים לצלם. הערכים ברשימה הזו מיוצגים באחוזים ביחס ל'רמת הזום שמוגדרת כברירת מחדל', שמוגדרת כ-100%. הרשימה עולה באופן מונוטונית ומכילה את הערך 100.

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

אפשר להפעיל את controller.getSupportedZoomLevels() אם מתקיימים התנאים הבאים:

  • controller משויך לתיעוד פעיל.
  • התמונה היא של כרטיסייה.

אחרת, תופיע הודעת שגיאה.

ההרשאה "captured-surface-control" לא נדרשת כדי לקרוא לשיטה הזו.

zoomLevel

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

בסיום הצילום, המאפיין יכיל את הערך האחרון של רמת הזום.

ההרשאה "captured-surface-control" לא נדרשת לקריאת המאפיין הזה.

onzoomlevelchange

פונקציית הטיפול באירועים הזו מאפשרת להאזין לשינויים ברמת הזום של הכרטיסייה שצולמה. אלה יכולים לקרות במקרים הבאים:

  • כשהמשתמש יוצר אינטראקציה עם הדפדפן כדי לשנות באופן ידני את רמת הזום של הכרטיסייה שצולמה.
  • בתגובה לקריאות של אפליקציית הצילום לשיטות של הגדרת הזום (כפי שמתואר בהמשך).

ההרשאה "captured-surface-control" לא נדרשת לקריאת המאפיין הזה.

increaseZoomLevel(),‏ decreaseZoomLevel() וגם resetZoomLevel()

השיטות האלה מאפשרות לשנות את רמת הזום של הכרטיסייה שצולמה.

increaseZoomLevel() ו-decreaseZoomLevel() משנים את רמת הזום לרמה הבאה או הקודמת, בהתאמה, בהתאם לסדר שמוחזר על ידי getSupportedZoomLevels(). resetZoomLevel() מגדיר את הערך כ-100.

כדי לקרוא לשיטות האלה, נדרשת ההרשאה "captured-surface-control". אם לאפליקציית הצילום אין את ההרשאה הזו, המשתמש יתבקש להעניק או לדחות אותה.

כל השיטות האלה מחזירות הבטחה (promise) שמתקבלת אם הקריאה מסתיימת בהצלחה, ונדחית אחרת. סיבות אפשריות לדחייה:

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

חשוב לציין: מומלץ להימנע משיחות אל decreaseZoomLevel() אם controller.zoomLevel == controller.getSupportedZoomLevels().at(0), ולהגן על שיחות אל increaseZoomLevel() באופן דומה באמצעות .at(-1).

בדוגמה הבאה מוסבר איך לאפשר למשתמש להגדיל את רמת הזום של כרטיסייה שצולמה ישירות מאפליקציית הצילום:

const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
  if (controller.zoomLevel >= controller.getSupportedZoomLevels().at(-1)) {
    return;
  }
  try {
    await controller.increaseZoomLevel();
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

בדוגמה הבאה מוסבר איך להגיב לשינויים ברמת הזום של כרטיסייה שצולמה:

controller.addEventListener('zoomlevelchange', (event) => {
  const zoomLevelLabel = document.querySelector('#zoomLevelLabel');
  zoomLevelLabel.textContent = `${controller.zoomLevel}%`;
});

זיהוי תכונות

כדי לבדוק אם יש תמיכה בממשקי API לבקרת משטחים שתועדו, משתמשים ב-:

if (!!window.CaptureController?.prototype.forwardWheel) {
  // CaptureController forwardWheel() is supported.
}

אפשר גם להשתמש בכל אחת מהממשקים האחרים של Captured Surface Control API, כמו increaseZoomLevel או decreaseZoomLevel, או אפילו לבדוק את כולם.

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

התכונה 'שליטה בשטח שצולם' זמינה בגרסה 136 של Chrome במחשב בלבד.

אבטחה ופרטיות

מדיניות ההרשאות של "captured-surface-control" מאפשרת לכם לקבוע לאילו אפליקציות הקלטה ולתגי iframe מוטמעים של צד שלישי תהיה גישה ל-Captured Surface Control. כדי להבין את הפשרות בנושא אבטחה, כדאי לעיין בקטע שיקולים לגבי פרטיות ואבטחה במאמר ההסבר על אמצעי הבקרה של משטח הנתונים המצולם.

הדגמה (דמו)

כדי לשחק עם 'שליטה במשטח שצולם', אפשר להריץ את הדמו ב-Glitch. חשוב לבדוק את קוד המקור.

משוב

צוות Chrome וקהילת תקני האינטרנט רוצים לשמוע על החוויות שלכם עם Captured Surface Control.

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

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

בעיה בהטמעה?

מצאתם באג בהטמעה של Chrome? או שההטמעה שונה מהמפרט? שולחים דיווח על באג בכתובת https://new.crbug.com. חשוב לכלול כמה שיותר פרטים, וגם הוראות לשחזור הבעיה. Glitch הוא כלי מצוין לשיתוף באגים שניתן לשחזור.