2016-04-15 1 views
3

У меня есть клиентское приложение iOS, которое использует GCDWebServer для обслуживания изображений и видео, хранящихся в папке NSSearchPathDirectory.DocumentDirectory приложения на моем устройстве.Как реализовать поддержку поиска видео со встроенным HTTP-сервером на iOS?

При запуске приложения, я начинаю экземпляр GCDWebServer и добавить обработчик ответа файл для моих запросов:

self.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerFileRequest.self) { request in 

    return GCDWebServerFileResponse(file: self.filePathForResponse(request.URL)) 
} 

я могу подтвердить, что в то время как приложение работает, я могу успешно загружать файлы с устройства:

curl -O http://192.168.0.15:8080/files/IMG_1213-1280x720.MOV 

мое приложение общается с устройством Chromecast, отправляя URL-адреса, как один выше для канала медиа и приемника приложение нагрузок Chromecast и воспроизводит видео в указанных URL-адресов - до сих пор все хорошо.

Моя проблема заключается в том, что я хочу реализовать поиск поддержки воспроизводимого в данный момент видео, и как только я отправлю запрос поиска на медиа-канал, я получаю сообщение об ошибке «Broken pipe» от GCDWebServer и воспроизведение видео прерывается , Вход с сервера выглядит следующим образом:

.... 
[DEBUG] Connection sent 32768 bytes on socket 24 
[DEBUG] Connection sent 32768 bytes on socket 24 
[ERROR] Error while writing to socket 24: Broken pipe (32) 
[DEBUG] Did close connection on socket 24 

Мое лучшее понимание проблемы заключается в том, что нормальное воспроизведение работает, потому что это то же самое, как и загрузка файла с начала до конца, и это может быть подано с обычным GCDWebServerFileResponse, однако поиск эквивалентен «перескакиванию» в другую часть файла, и я не уверен, что чтение такого файла будет работать с моей конфигурацией.

  • Есть ли способ, которым я могу настроить GCDWebServer, чтобы сделать эту работу? Я знаю, что проблема может быть решена, потому что есть несколько живых приложений, которые это делают.
  • Должен ли я использовать сервер, который поддерживает другие протоколы, такие как HLS или RTSP?
  • Нужно ли кодировать мои видео файлы определенным образом?

Для справки Я также попробовал другой HTTP-сервер под названием Swifter, но столкнулся с той же проблемой.

ответ

2

iOS 'AVPlayer сначала запрашивает размер файла, а затем запрашивает сервер для кусков данных, включая требуемый диапазон в запросе. В этом answer показана сетевая активность AVPlayer, а код состояния ответа - 206, то есть Partial Content.

Таким образом, мы должны реагировать только с нужной порции данных:

webServer?.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, asyncProcessBlock: { (request, completionBlock) in 
    let response = GCDWebServerFileResponse(file: path, byteRange: request.byteRange) 
    completionBlock(response) 
}) 

Пожалуйста, обратите внимание, что это очень важно, чтобы проверить, является ли request.byteRange определяется вызовом request.hasByteRange().

Используя код, который я предоставил, я смог воспроизвести видео с помощью AVPlayer или веб-браузера, а также очистить/искать время.

+0

Я изменил свой код, чтобы использовать 'byteRange', как было предложено, однако в моем случае потребитель не является AVPlayer, а Chromecast отправляет запросы на видеоданные. Похоже, что byteRange.length == -1, contentType = nil и contentLength = -1.Даже когда вы используете это с 'hasByteRange()', видео очень прерывисто, и я получаю много: [ERROR] Ошибка при записи в гнездо 18: Broken pipe (32) – bizz84

+0

Я наблюдал, как клиенты (AVPlayer или Chrome) потребляют контент: после первоначальных запросов на получение размера видео они запрашивают целое видео с самого начала. После того, как клиент имеет достаточно буферизованных данных, он перестает получать его, закрывает соединение, а значит, и обрывает трубку. Когда клиент нуждается в большем количестве данных (т. Е. Проигрыватель воспроизводит почти все буферизованное видео или пользователь начал очистку в другом месте), клиент запускает новый запрос, с byterange, который начинается не с нуля, а заканчивается в конце файла. –

+0

Например, если размер файла равен 500, и есть два запроса: 1. 0-499 - после того, как игрок имеет достаточно буферизированных данных, он закрывает соединение (на самом деле он получил только 100 байт) 2. 101-499 - когда буфер становится почти пустым, игрок снова запускает предварительную загрузку, но не запрашивает уже буферизованные данные. Это объясняет ошибки обрыва труб. –