개인프로젝트 고민
안녕하세요 선생님,
제공해주신 강의덕분에 iOS 방향으로 공부하고있는 학생입니다.
좋은 내용과 쉬운 설명으로 iOS입문에 큰 도움이 되었습니다!
다름이 아니라 강의해주신 NetflixClone 내용을 바탕으로 개인프로젝트를 진행하고 있습니다.
프로젝트 내용은
iOS 기기에서 rtmp 형식으로 라이브 방송을 송출하여 타 iOS기기에서 방송을 시청할 수 있는 App을 제작하고 있습니다. [ iOS(RTMP) 송출 -> Nginx(HLS) -> iOS(시청)] 하지만, 약 2주일동안 삽질을 하고 있는 부분이 있어 혹시나 하는 마음에 질문 드려봅니다.
제가 삽질하고 있는 부분은 Youtube, Twitch처럼 TableView로 방송목록을 보여줘야 하는데 구현된 부분은 DB에서 HLS(m3u8) URL과 해당 방송 내용만 제공하고 있기에 thumbnail로 제공할 이미지를 HLS URL에서 추출하는 방법을 시도하고 있습니다.
시도 1. AVAssetImageGenerator
Apple 공식문서에서 제공하는 (https://developer.apple.com/documentation/avfoundation/media_reading_and_writing/creating_images_from_a_video_asset) HTTP Live Streaming (HLS) 형식을 cgImage 형식으로 변환하는 방식을 사용했는데 AVPlayer에서 전체 시간이 뜨는 m3u8형식의 URL은 잘 작동합니다. 그런데 제가 원하는 방송 형식의 라이브 형식은 image를 가져오지 못하더군요.
시도 2.
각 Cell마다 AVPlayerLayer를 설정해 NetflixClone 내용과 비슷하게 TableView cellForRowAt 함수에서 각각 Cell에 있는 변수에 didSet으로 URL을 주면 AVPlayerLayer를 올리는 방식을 사용하였습니다. 재생 설정은 하지 않았기에 정지된 화면을 이미지처럼 보이게 설정하였습니다. 의도대로 각 셀마다 thumbnail이 표시되긴 하였지만, Cell을 다시 로드할때 thumbnail이 늦게 표시되거나 다른 영상이 중복되어 표시되는 문제가 있었습니다.
시도 2.1
ACThumbnailGenerator : https://github.com/acotilla91/ACThumbnailGenerator-Swift
위 라이브러리는 HLS/.m3u8를 UIImage로 추출하는 라이브러리입니다. UIImage로 추출하는 시간이 다소 있기에 추출하면 Image Cache처리 하여 다시 로드할때 시간을 줄였지만, 첫 로드할때의 로딩시간이 길어 다소 애매한 상황입니다.
if URL의 Cache가 있는가? {
cell.liveView.image = Image Cache
} else {
AVPlayerLayer = URL (시도 2. 방법)
ACThumbnailGenerator로 URL 추출 후 Image Cache (이후 재로딩을 위함)
}
안녕하세요
일단 네이티브 앱에서 썸네일용 이미지를 만드는 개념은 잘 알고 계신 것 같습니다.
일반적으로 클라이언트(네이티브)쪽에서 썸네일을 직접 만들어 쓰는 방법 보다는 서버에서 처리하고 보내주는 방식을 많이 사용합니다.
어느 방향으로 할지 대략적인 장단점을 생각해 보시면 개발방향을 결정하는데 도움이 되지 않을까 싶습니다.
서버에서 썸네일 만드는 경우
말씀하신 구조 기준에서는 Nginx에서 썸네일을 만드는 방법입니다.
서버에서 처리하니 일관성 유지에 좋고 한번 만든 영상의 썸네일은 다시 안만들고 재사용도 되고 클라이언트가 빠르게 썸네일을 받을 수 있습니다.
대신 처리 할게 많다면 서버의 cpu, ram등의 자원 사용량이 높아지는걸 고려해야 합니다.
송출하는 쪽에서 썸네일 만드는 경우
송출하는 앱 기준에서는 썸네일 나올 필요가 없으니 빨리 안나오는 문제 같은걸 생각하지 않아도 됩니다.
송출하는 영상 하나 기준으로 주기적으로 썸네일을 만들어 보내면 되니 부하도 별로 없을 것입니다.
대신 썸네일 전송하는 정책에 고민이 좀 필요할 것 같습니다.
예를 들어 썸네일 보내기 실패하는 케이스 발생시 수신부에서 썸네일이 계속 없는 문제가 생길 경우등 에러처리에 고려사항이 꽤 있어 보입니다.
그리고 진행해보신 수신부에서 썸네일을 만드는 경우
해보신 것 처럼 썸네일 만들어서 보이는데 까지 시간이 걸리는 문제가 있습니다.
썸네일을 만들기 위해서는 어쩔 수 없이 미디어 스트림의 일정부분을 받아오고 그 안에서 특정 프레임을 캡쳐한다는 작업 자체가 필요한데 그 작업은 시간이 걸릴 수 밖에 없는 큰 작업입니다.
이 때문에 눈에 띄는 딜레이는 필연적이라 생각됩니다.
대안은 nginx에서 저해상도 영상도 송출되도록 작업해 놓고 썸네일 만드는 주소는 저해상도 주소로 하면 많은 시간단축이 예상됩니다.
끝으로 공통적으로 생각해야 할 부분은
썸네일은 어디서 만들던 저화질로 만들어야 합니다. 고화질 썸네일이 모바일 환경에서 필요한 경우는 거의 없습니다.
수신부의 캐싱 처리는 어떻게 만들더라도 무조건 해야하는 필수요소 입니다.
서버에서 만든 썸네일을 수신하는 클라이언트가 많다면 CDN등을 사용하여 캐싱처리하는게 트래픽에 매우 효율적입니다.
생각나는 개발방향은 이 정도 같습니다.
이 예시들을 적절히 섞는것도 방법일 수 있으니 자신의 상황에 맞는 전략을 충분히 구상해 보시면 좋을 것 같습니다.
그리고 질문내용중에 순서에 안맞게 나오는 건 셀의 인덱스 순서와 데이터 순서를 맞는지 확인하는 로직이 반드시 들어가야 엉뚱한 썸네일이 나오는 걸 방지할 수 있습니다.
예) 썸네일 데이터 안에서 5번 index라는 값을 같이 갖고 있어서 indexPath.row가 5가 맞으면 보여주는 식으로요
도움이 되셨길 바랍니다.
답글
양윤석
2023.09.26프로젝트를 혼자 진행하다 보니 수신부에서 진행해야 한다는 편향된 생각을 가지고 있었던것 같네요. 뒤통수를 얻어맞은듯한 기분입니다. 덕분에 또 하나 배워갑니다. 정말 감사합니다!