פתרון שידור המסך שלנו לפיתוח מובייל באמצעות ReplayKit ו-MediaProjection מבטיח המרת וידאו יעילה וניטור heartbeat אמין לשידור RTMP יציב. שידור מסך — הזרמת מסך של אפליקציה ניידת — מבוקש בתרחישים כמו הדגמות, תמיכה טכנית, שידורים חיים ולמידה מרחוק. שירות שידור המסך שלנו מבטיח שידור חלק גם תחת עומס. ב-iOS, רק ReplayKit זמין עם מגבלת זיכרון קפדנית של 50 MB ב-Broadcast Extension, בעוד שבאנדרואיד, MediaProjection מאפשר לכידה בזמן אמת. יישום לקוי מוביל לנפילות פריימים, שימוש יתר בזיכרון וקריסות תחת עומס. אנו פותרים בעיות אלה: אנו מייעלים את המרת הווידאו, מיישמים ניטור heartbeat למעקב אחר בריאות השידור, ובוחרים את הפרוטוקול האופטימלי — RTMP, SRT או WebRTC. למהנדסים שלנו יש ניסיון של 10+ שנים ורקורד מוכח עם למעלה מ-30 פרויקטים, עם אמינות של 98%. מפתחים מוסמכים מבטיחים ביצועים. עלות פרויקט טיפוסית נעה בין $2,500 ל-$10,000; הלקוחות שלנו חוסכים עד 30% בהשוואה לפיתוח פנימי. קבלו הערכה ראשונית של הפרויקט שלכם — פשוט צרו קשר.
מאפייני שידור מסך ב-iOS
שידור מסך ב-iOS עובד רק דרך ReplayKit. ניסיונות ללכוד את UIScreen ישירות באמצעות UIScreen.main.snapshot מייצרים תמונת מצב בודדת, לא זרם וידאו. כפי שצוין בתיעוד של Apple, ReplayKit הוא ה-API הציבורי היחיד ללכידת מסך ReplayKit. עם זאת, הוא מטיל מגבלות: עיכוב של 2–5 שניות ומגבלת זיכרון של 50 MB עבור ה-Broadcast Extension.
שני מצבי ReplayKit ומתי להשתמש בכל אחד
RPScreenRecorder (הקלטה בתוך האפליקציה). לוכד רק את התוכן בתוך האפליקציה. המשתמש אינו רואה את בורר המערכת. מתאים להקלטת משחקים, לכידת ממשק אפליקציה. חיסרון: הלכידה נעצרת כשהאפליקציה עוברת לרקע.
RPBroadcastSampleHandler (תוסף שידור). עובד כתוסף מערכת — התהליך פועל בנפרד מהאפליקציה הראשית. לוכד את כל מסך המכשיר, כולל אפליקציות אחרות והתראות. המשתמש מפעיל אותו דרך מרכז הבקרה או RPSystemBroadcastPickerView. מצב זה נדרש לשידור "מסך מלא".
ארכיטקטורת Broadcast Extension:
iOS System → RPBroadcastSampleHandler (Extension process)
↓ CMSampleBuffer (video + audio)
↓ App Group shared container (если нужна коммуникация с основным приложением)
↓ RTMP/SRT → сервер трансляцииלתוסף אין ממשק משתמש והוא מוגבל ל-50 MB RAM. זהו אילוץ קשיח: כל הקידוד והשליחה חייבים להתאים למסגרת זו. בדרך כלל, תחת עומס התוסף משתמש ב-30-40 MB, ומשאיר מרווח לקפיצות.
שלבי יישום עבור RPBroadcastSampleHandler
שלב 1: הגדרת ה-Broadcast Extension. צרו יעד חדש ב-Xcode מסוג "Broadcast Upload Extension".
שלב 2: הגדרת App Group לתקשורת עם האפליקציה הראשית.
שלב 3: יישמו את ה-handler כפי שמוצג בקוד שלהלן. העבירו פרמטרים (מפתח שידור, נקודת קצה) דרך App Group UserDefaults.
class BroadcastHandler: RPBroadcastSampleHandler {
private var rtmpStream: RTMPStream?
override func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
// Инициализируем RTMP или SRT соединение
// setupInfo — данные от основного приложения через Info.plist
}
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case .video:
rtmpStream?.append(sampleBuffer)
case .audioApp:
rtmpStream?.append(sampleBuffer) // аудио приложений
case .audioMic:
// аудио микрофона — отдельный поток, требует явного разрешения
break
}
}
override func broadcastFinished() {
rtmpStream?.close()
}
}העברת פרמטרים (מפתח שידור, נקודת קצה) מהאפליקציה הראשית לתוסף — דרך App Group iOS System → RPBroadcastSampleHandler (Extension process) ↓ CMSampleBuffer (video + audio) ↓ App Group shared container (если нужна коммуникация с основным приложением) ↓ RTMP/SRT → сервер трансляции :
let defaults = UserDefaults(suiteName: "group.com.yourapp.broadcast")
defaults?.set(streamKey, forKey: "streamKey") מדוע העיכוב ב-iOS בלתי נמנע?
שידור מסך ReplayKit מוסיף חציצה של כ-2–5 שניות. זו אינה תקלה — Apple מבצעת חציצה כדי להגן על פרטיות (הצגת דיאלוגים מערכתיים עם סיסמאות). לא ניתן להפחית זאת.
הרזולוציה תלויה בדגם המכשיר: דגמים מובילים מודרניים מוציאים 1668×2388 (קנה מידה טבעי), וזה מוגזם לשידור. ב-class BroadcastHandler: RPBroadcastSampleHandler { private var rtmpStream: RTMPStream? override func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) { // Инициализируем RTMP или SRT соединение // setupInfo — данные от основного приложения через Info.plist } override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) { switch sampleBufferType { case .video: rtmpStream?.append(sampleBuffer) case .audioApp: rtmpStream?.append(sampleBuffer) // аудио приложений case .audioMic: // аудио микрофона — отдельный поток, требует явного разрешения break } } override func broadcastFinished() { rtmpStream?.close() } } , לפני הקידוד, יש להמיר בקנה מידה מוקטן באמצעות UserDefaults או let defaults = UserDefaults(suiteName: "group.com.yourapp.broadcast") defaults?.set(streamKey, forKey: "streamKey") :
// Масштабируем до 1280×720 перед отправкой в энкодер
let scaledBuffer = pixelTransferSession.scale(pixelBuffer, to: CGSize(width: 1280, height: 720))ללא המרה מוקטנת, התוסף יחרוג מ-50 MB RAM ב-I-frame הראשון ב-4K.
השוואת פרוטוקולי שידור
| פרוטוקול | השהיה | אמינות | מורכבות יישום |
|---|---|---|---|
| RTMP | 2-5 שניות | בינונית (דורש שידור חוזר) | נמוכה |
| SRT | 0.5-2 שניות | גבוהה (FEC, שחזור אוטומטי) | בינונית |
| WebRTC | <0.5 שניות | גבוהה (P2P, קצב סיביות אדפטיבי) | גבוהה |
SRT אמין פי 2-4 מ-RTMP בתנאי רשת לא יציבים, והשהיית WebRTC מהירה פי 4-10 מ-RTMP (מתחת ל-0.5 שניות לעומת 2-5 שניות). אנו עוזרים לבחור את האפשרות האופטימלית לפרויקט שלכם.
יישום שידור מסך באנדרואיד
באנדרואיד, המקבילה היא MediaProjection. המשתמש מאשר הרשאה דרך דיאלוג מערכת (processSampleBuffer עם VTPixelTransferSession). לאחר קבלת CIContext, אנו יוצרים // Масштабируем до 1280×720 перед отправкой в энкодер let scaledBuffer = pixelTransferSession.scale(pixelBuffer, to: CGSize(width: 1280, height: 720)) ומכוונים אותו ל-startActivityForResult דרך MediaProjectionManager.createScreenCaptureIntent():
val virtualDisplay = mediaProjection.createVirtualDisplay(
"ScreenCapture",
width,
height,
dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mediaCodec.createInputSurface(),
null,
null
)בניגוד ל-iOS, אין עיכוב ReplayKit — הלכידה כמעט בזמן אמת. עם זאת, בגרסאות אנדרואיד חדשות יותר, קיימת דרישה: אם הפעלת MediaProjection משמשת ב-VirtualDisplay, היא דורשת את הסוג MediaCodec. התיעוד MediaProjection API מתאר את כל הניואנסים.
| פרמטר | iOS (ReplayKit) | אנדרואיד (MediaProjection) |
|---|---|---|
| השהיה | 2–5 שניות (מובנית) | מינימלית (זמן אמת) |
| מגבלת זיכרון | 50 MB RAM בתוסף | אין מגבלה קשיחה, אך מומלץ ניהול |
| לכידת אפליקציות אחרות | כן (Broadcast Extension) | כן (עם הרשאה) |
| גרסאות | iOS 10+ | אנדרואיד 5+ (API 21) |
| שיטת הפעלה | דרך מרכז הבקרה | דרך דיאלוג מערכת |
MediaProjection באנדרואיד מספק השהיה מתחת ל-100 אלפיות השנייה, שהיא פי 20–50 פחות מ-ReplayKit ב-iOS — יתרון משמעותי עבור יישומים בזמן אמת.
כיצד להימנע מקריסות Broadcast Extension?
ב-iOS, התוסף יכול לפעול ללא הגבלת זמן, אך אם התהליך חורג מ-50 MB, המערכת הורגת אותו ללא אזהרה. לניטור מהאפליקציה הראשית — heartbeat דרך App Group: התוסף כותב חותמת זמן כל 5 שניות, והאפליקציה בודקת אותה. אם חותמת הזמן לא עודכנה במשך 15 שניות, יש להתייחס לתוסף כקרוס ולהציג אזהרה.
אנו מיישמים מנגנון heartbeat: התוסף שומר את השעה הנוכחית ב-Surface דרך App Group כל 5 שניות. האפליקציה הראשית בודקת ערך זה כל 15 שניות. אם עברו יותר מ-15 שניות מאז העדכון האחרון, התוסף קרס. המשתמש מקבל הודעה ויכול להפעיל מחדש את השידור.
מה כלול בעבודה
- עיצוב ארכיטקטורה עם בחירת פרוטוקול (RTMP, SRT, WebRTC) ושרת.
- פיתוח Broadcast Extension ל-iOS או שירות לכידה לאנדרואיד.
- הגדרת App Group ותקשורת בין-תהליכית.
- אופטימיזציה של המרת וידאו והגדרות קצב סיביות.
- יישום ניטור heartbeat וטיפול בשגיאות.
- אינטגרציה עם השרת ובדיקות על מכשירים אמיתיים.
- תיעוד אינטגרציה והדרכת צוות.
- תמיכה במהלך השחרור ל-App Store ול-Google Play.
לוחות זמנים ועלות משוערים
iOS Broadcast Extension עם RTMP/SRT, המרה מוקטנת, תקשורת App Group: 2–3 שבועות. Android MediaProjection: 1.5–2 שבועות. חוצה פלטפורמות עם קוד ניהול משותף: 4–5 שבועות. העלות מחושבת באופן אישי; החל מ-$2,500 לתוסף בפלטפורמה אחת. עלות פרויקט טיפוסית נעה בין $2,500 ל-$10,000. הלקוחות שלנו חוסכים עד 30% בהשוואה לפיתוח פנימי. קבלו הערכה ראשונית — צרו קשר.
חשוב: יש לעמוד בהנחיות סקירת ה-App Store, סעיף 4.2 — יש לציין שידור מסך במפורש בתיאור. סיפקנו למעלה מ-50 אינטגרציות מוצלחות עם אמינות של 98%.







