Кто-нибудь знает, есть ли возможность загружать буферы кадров из расширения Broadcast Upload Extension в хост-приложение, или я должен загружать их непосредственно в серверную часть? Моя цель - перехватить буферы кадров из набора воспроизведения, отправить их в мое приложение и транслировать видео через мое приложение с помощью Webrtc. Буду признателен за любую помощь. Заранее спасибо.
Как реализовать загрузку в расширении загрузки вещания (iOS)?
Ответы (3)
При запуске широковещательной передачи загружаются только расширение широковещательной загрузки и расширение пользовательского интерфейса широковещательной передачи. И, насколько мне известно, не существует программного способа запуска вашего хост-приложения и потоковой передачи в него каких-либо данных в фоновом режиме.
Но вы можете реализовать всю логику в расширении Broadcast Upload. Ваша RPBroadcastSampleHandler
реализация питается видео CMSampleBuffer
s. Вся логика постобработки и загрузки зависит от реализации. Таким образом, вы можете распаковывать и обрабатывать кадры, а затем загружать их на свой сервер любым подходящим способом. Если вам нужны какие-либо сведения о конфигурации или авторизации, вы можете просто установить их в расширении широковещательного пользовательского интерфейса или даже в своем хост-приложении, а затем просто сохранить их в общем хранилище.
Информации об этом нет ни в Интернете, ни в документации Apple. Но вы все еще можете:
- Посмотреть видео о WWDC 2016
Go Live with ReplayKit
- Прочтите
RPBroadcastSampleHandler
документацию - Прочтите этот весьма полезный пост в блоге (на китайском языке): http://blog.lessfun.com/blog/2016/09/21/ios-10-replaykit-live-and-broadcast-extension/
- Поиграйте с реализацией заглушки расширения загрузки (просто создайте цель в Xcode)
Точно так же я пробовал с комбинацией Replay Kit
и webRTC. Основная проблема webRTC на iOS заключается в том, что webRTC не может обрабатывать видеопоток, если он уходит в фоновый режим. Итак ... вы можете транслировать видеопоток с экрана вашего приложения в webRTC, пока ваше приложение для видеочата находится на переднем плане, но для потоковой передачи другого приложения, когда ваше приложение переходит в фоновый режим, вы не сможете обрабатывать видеопоток, а только голосовую связь через webRTC.
Вам лучше загрузить его на сервер из расширения загрузки, я уже потратил слишком много времени на подключение расширения загрузки к хост-приложению ... нет абсолютно никакого контроля над расширением загрузки.
У меня есть для вас код, я уже реализовал его в своем проекте и обсуждал в google-группах: https://groups.google.com/d/msg/discuss-webrtc/jAHCnB12khE/zJEu1vyUAgAJ
Я перенесу сюда код для следующих поколений:
Прежде всего, я создал дополнительный класс в широковещательном расширении для управления кодом, связанным с WebRTC, и назвал его PeerManager.
Настройте видеодорожку с локальным потоком, будьте осторожны, вы должны сделать это до создания локального предложения.
private func setupVideoStreaming() {
localStream = webRTCPeer.peerConnectionFactory.mediaStream(withStreamId: "\(personID)_screen_sharing")
videoSource = webRTCPeer.peerConnectionFactory.videoSource()
videoCapturer = RTCVideoCapturer(delegate: videoSource)
videoSource.adaptOutputFormat(toWidth: 441, height: 736, fps: 15)
let videoTrack = webRTCPeer.peerConnectionFactory.videoTrack(with: videoSource, trackId: "screen_share_track_id")
videoTrack.isEnabled = true
localStream.addVideoTrack(videoTrack)
for localStream in webRTCPeer.localPeerConnection.peerConnection.localStreams {
webRTCPeer.localPeerConnection.peerConnection.remove(localStream)
}
webRTCPeer.localPeerConnection.peerConnection.add(localStream)
}
Я получил обратный вызов от системы, которая предоставляет мне CMSampleBuffer, я конвертирую его в RTCVideoFrame и отправляю в videoSource (эмулировать VideoCapturer)
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case RPSampleBufferType.video:
// Handle video sample buffer
guard peerManager != nil, let imageBuffer: CVImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
break
}
let pixelFormat = CVPixelBufferGetPixelFormatType(imageBuffer) // kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
let timeStampNs: Int64 = Int64(CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) * 1000000000)
let rtcPixlBuffer = RTCCVPixelBuffer(pixelBuffer: imageBuffer)
let rtcVideoFrame = RTCVideoFrame(buffer: rtcPixlBuffer, rotation: ._0, timeStampNs: timeStampNs)
peerManager.push(videoFrame: rtcVideoFrame)
case RPSampleBufferType.audioApp:
break
case RPSampleBufferType.audioMic:
break
}
}
Код из peerManager, это реализация функций push из кода выше. Ничего странного здесь нет, мы эмулируем поведение Capturer с помощью delegate.
func push(videoFrame: RTCVideoFrame) {
guard isConnected, videoCapturer != nil, isProcessed else {
return
}
videoSource.capturer(videoCapturer, didCapture: videoFrame)
}
Теперь вы готовы сгенерировать локальное предложение, отправить его и передать все, что захотите. Попробуйте проверить свое местное предложение. Если вы все сделаете правильно, вы увидите в своем предложении a = sendonly.
P.S. Как предлагает VladimirTechMan, вы также можете проверить образец кода расширения вещания в демонстрационном приложении AppRTCMobile. Я нашел для вас ссылку, это пример Objective-C https://webrtc.googlesource.com/src/+/358f2e076051d28b012529d3ae6a080838d27209 Вас должны заинтересовать файлы ARDBroadcastSampleHandler.m / .h и ARDExternalSampleCapturer.m / .h. Никогда не забывайте, что вы можете собрать его самостоятельно согласно инструкции https://webrtc.org/native-code/ios/