Какой у вас опыт работы с видеостримингом в iOS?

Ответ

Да, есть опыт работы с фреймворками AVFoundation и AVKit для воспроизведения, записи и потоковой передачи видео.

Ключевые задачи и реализации:

  1. Воспроизведение HLS-потоков: Использовал AVPlayer и AVPlayerViewController для стриминга с адаптивным битрейтом.
  2. Оптимизация воспроизведения: Настраивал кэширование (AVAssetResourceLoaderDelegate) и буферизацию для обеспечения плавности, особенно в условиях нестабильной сети.
  3. Обработка состояния: Реализовывал наблюдение за статусом плеера (KVO на player.status, playerItem.status) и буфера (playerItem.loadedTimeRanges).
  4. Фоновое воспроизведение: Настраивал аудиосессию и фоновые режимы в Info.plist.

Пример базовой настройки HLS-стриминга:

import AVKit

let streamURL = URL(string: "https://example.com/master.m3u8")!
let playerItem = AVPlayerItem(url: streamURL)
let player = AVPlayer(playerItem: playerItem)

let playerViewController = AVPlayerViewController()
playerViewController.player = player

present(playerViewController, animated: true) {
    player.play()
}

Для более сложных протоколов (например, RTMP) использовал сторонние решения, такие как HaishinKit (Larix).

Best Practices:

  • Всегда предварительно проверяйте URL на доступность.
  • Используйте AVAsset для предзагрузки метаданных.
  • Освобождайте ресурсы (player.pause(), player.replaceCurrentItem(with: nil)) при уходе с экрана.

Ответ 18+ 🔞

А, ну вот, значит, про видеоопыты мои спрашиваешь? Да, блядь, работал я с этими вашими AVFoundation и AVKit. Не то чтобы прям всю подноготную знаю, но всякие базовые штуки — воспроизвести, записать, поток пустить — это да, делал.

Чем конкретно страдал:

  1. HLS-потоки гонял: Берёшь AVPlayer с AVPlayerViewController, суёшь ему ссылку на плейлист (.m3u8), и он уже сам, хитрая жопа, качество подбирает под твою сеть. Удобно, чё.
  2. Чтоб не тормозило: Тут, конечно, приходилось мозги включать. Настраивал кэширование через какого-то AVAssetResourceLoaderDelegate, следил, чтобы буфер не пустым был. Особенно когда сеть начинает себя вести как последняя манда с ушами — то есть, то нет.
  3. Слежка за состоянием: Это отдельная песня. Вешался на все эти статусы плеера и айтема через KVO, смотрел, что там с буфером нагрузилось (loadedTimeRanges). Чтобы пользователь не сидел, как дурак, перед чёрным экраном, если что-то пошло не так.
  4. Фоновая работа: Ну, чтоб музычка из видео играла, когда приложение свёрнуто. В Info.plist галочки нужные тыкал, аудиосессию правильную выставлял.

Вот, смотри, как это обычно просто выглядит, если по-быстрому:

import AVKit

let streamURL = URL(string: "https://example.com/master.m3u8")!
let playerItem = AVPlayerItem(url: streamURL)
let player = AVPlayer(playerItem: playerItem)

let playerViewController = AVPlayerViewController()
playerViewController.player = player

present(playerViewController, animated: true) {
    player.play()
}

А вот если тебе нужно что-то более экзотическое, вроде RTMP, то тут нативные штуки уже руки выкручивают. Приходилось брать сторонние библиотеки, типа HaishinKit (он же Larix). С ними, конечно, тоже весело, но хоть работает.

И главное, что усвоил, чтоб не обосраться:

  • Всегда сначала проверяй, жива ли твоя ссылка, а то потом будешь как дурак ошибки ловить.
  • Метаданные (AVAsset) лучше подгрузить заранее, до того как показывать плеер.
  • И, ёпта, не забудь всё почистить, когда экран закрываешь! Останови плеер (pause()), обнули текущий айтем (replaceCurrentItem(with: nil)). А то он так в памяти и будет висеть, жрать батарею, пока система не прибьёт.