iOS AVPlayer 시작 지연을 줄이는 방법


115

아래 질문에 대한 참고 : 모든 자산은 장치에서 로컬이며 네트워크 스트리밍이 발생하지 않습니다. 비디오에는 오디오 트랙이 포함되어 있습니다.

문제의 비디오 클립을 시작하려면 최소한의 지연으로 비디오 파일을 재생해야하는 iOS 응용 프로그램에서 작업 중입니다. 불행히도 우리는 실제로 시작해야 할 때까지 특정 비디오 클립이 다음에 무엇인지 알 수 없습니다. 구체적으로 : 하나의 비디오 클립이 재생 될 때 (대략) 10 개의 비디오 클립의 다음 세트가 무엇인지 알 수 있지만 다음 클립을 '즉시'재생할 때까지 정확히 어떤 클립인지 알 수 없습니다.

실제 시작 지연을 확인하기 위해 제가 한 것은 addBoundaryTimeObserverForTimes비디오 플레이어 를 호출 하는 것입니다. 1 밀리 초의 시간을두고 비디오가 실제로 재생되기 시작한시기를 확인하고 해당 타임 스탬프의 차이를 재생을 시작할 자산을 나타내는 코드입니다.

지금까지 본 것에서 AVAsset로딩 조합을 사용하고 AVPlayerItem준비가되면 생성 한 다음 AVPlayerStatusReadyToPlay플레이를 호출하기 전에 대기하는 것이 시작하는 데 1 ~ 3 초가 걸리는 경향이 있음을 알았습니다. 클립.

나는 그 이후로 거의 동등하다고 생각하는 것으로 전환했습니다. 전화를 걸고 플레이를 [AVPlayerItem playerItemWithURL:]기다리고 AVPlayerItemStatusReadyToPlay있습니다. 거의 동일한 성능.

내가 관찰 한 한 가지는 첫 번째 AVPlayer 항목로드가 나머지 항목보다 느리다는 것입니다. 한 가지 아이디어는 첫 번째 비디오를 재생하기 전에 짧거나 비어있는 자산으로 AVPlayer를 미리 비행하는 것입니다. [ 처음 소리가 재생 될 때 AVAudioPlayer의 느린 시작

가능한 한 비디오 시작 시간을 줄이고 실험 할 아이디어가 있지만 도움이 될 수있는 모든 사람의 지침을 받고 싶습니다.

업데이트 : 아래 아이디어 7, 구현시 약 500ms의 스위칭 시간이 발생합니다. 이것은 개선 된 것이지만 이것을 더 빨리 얻는 것이 좋을 것입니다.

아이디어 1 : N AVPlayers 사용 (작동하지 않음)

~ 10 개의 AVPPlayer개체를 사용하고 ~ 10 개의 클립을 모두 시작 및 일시 중지하고, 어떤 클립이 정말 필요한지 알고 나면 올바른 항목으로 전환하고 일시 중지를 해제합니다.AVPlayer 하고 다음주기를 위해 다시 시작합니다.

AVPlayer'siOS에서 약 4 개의 활성 제한이 있음을 읽었으므로 이것이 작동하지 않는다고 생각합니다 . 여기 StackOverflow에서 누군가가 이것에 대해 물어 보았고 , 4 개의 AVPlayer 제한에 대해 알아 냈습니다 : fast-switching-between-videos-using-avfoundation

아이디어 2 : AVQueuePlayer 사용 (작동하지 않음)

10 개를 AVPlayerItems넣는 AVQueuePlayer것이 원활한 시작을 위해 모두 미리로드 될 것이라고 생각하지 않습니다 . AVQueuePlayer대기열이며 대기열에있는 다음 동영상 만 즉시 재생할 수 있도록 준비합니다. 나는 그것을 시작할 시간이 될 때까지 ~ 10 개의 비디오 중 어떤 것을 재생하고 싶은지 모르겠다. ios-avplayer-video-preloading

아이디어 3 : AVPlayerItems백그라운드에서 로드, 재생 및 유지 (아직 100 % 확실하지는 않지만 좋지 않음)

백그라운드에서 각 비디오 클립의 첫 번째 초를로드 및 재생하고 (비디오 및 오디오 출력 억제) 각각에 대한 참조를 유지하고 AVPlayerItem어떤 항목에 대해 재생해야하는지 알 때 이점이 있는지 살펴보고 있습니다. 진짜로 바꾸고 배경 AVPlayer를 활성으로 바꿉니다. 헹구고 반복하십시오.

이론은 최근에 재생 된 AVPlayer/AVPlayerItem의가 후속 재생을 더 빠르게 할 수 있도록 준비된 리소스를 여전히 보유 할 수 있다는 것입니다. 지금까지 이것의 이점을 보지 못했지만 AVPlayerLayer배경에 대한 설정이 정확 하지 않을 수 있습니다 . 나는 이것이 내가 본 것에서 정말로 개선 될 것 같지 않다.

아이디어 4 : 다른 파일 형식을 사용하세요.로드가 더 빠른 파일 형식일까요?

현재 .m4v (비디오 -MPEG4) H.264 형식을 사용하고 있습니다. H.264에는 다양한 코덱 옵션이 있으므로 일부 옵션이 다른 옵션보다 빠르게 검색 될 수 있습니다. 파일 크기를 더 작게 만드는 고급 설정을 사용하면 검색 시간이 늘어나지 만 다른 방식으로가는 옵션은 찾지 못했습니다.

아이디어 5 : 무손실 비디오 형식 + AVQueuePlayer의 조합

로드 속도가 빠르지 만 파일 크기가 제정신이 아닐 수있는 비디오 형식이있는 경우 한 가지 아이디어는 각 비디오 클립의 처음 10 초를 부풀어도로드 속도가 빠른 버전으로 미리 준비하는 것입니다. H.264로 인코딩 된 자산을 사용합니다. AVQueuePlayer를 사용하고 압축되지 않은 파일 형식에 처음 10 초를 추가하고 최대 10 초의 준비 / 사전로드 시간을 가져 오는 H.264 형식의 파일을 추가합니다. 그래서 저는 두 세계 모두에서 '최고'를 얻었습니다. 시작 시간이 빠르지 만 더 컴팩트 한 형식의 이점도 있습니다.

아이디어 6 : 비표준 AVPlayer 사용 / 직접 작성 / 다른 사람 사용

내 필요를 감안할 때 AVPlayer를 사용할 수 없지만 AVAssetReader에 의존하고 처음 몇 초 동안 디코딩 (아마도 원시 파일을 디스크에 기록)하고 재생시 원시 형식을 사용하여 재생해야합니다. 뒤로 빨리. 나에게는 거대한 프로젝트처럼 보이며 순진하게 진행하면 불분명하거나 더 잘 작동하지 않을 것입니다. 디코딩되고 압축되지 않은 각 비디오 프레임은 2.25MB입니다. 순진하게 말해서, 비디오에 대해 ~ 30fps로 가면 ~ 60MB / s의 디스크에서 읽기 요구 사항으로 끝날 것입니다. 이는 아마도 불가능하거나 밀어 붙일 것입니다. 분명히 우리는 어느 정도의 이미지 압축 (아마도 PVRTC를 통한 기본 openGL / es 압축 형식)을 수행해야합니다 ...하지만 그건 미친 짓입니다. 제가 사용할 수있는 도서관이있을 수 있을까요?

아이디어 7 : 모든 것을 단일 영화 자산으로 결합하고 seekToTime

위의 일부보다 쉬울 수있는 한 가지 아이디어는 모든 것을 단일 영화로 결합하고 seekToTime을 사용하는 것입니다. 문제는 우리가 모든 곳을 뛰어 다니는 것입니다. 본질적으로 영화에 무작위로 액세스합니다. 나는 이것이 실제로 잘 될 것이라고 생각합니다 : avplayer-movie-playing-lag-in-ios5

어떤 접근 방식이 가장 좋을 것이라고 생각하십니까? 지금까지 지연을 줄이는 측면에서 그렇게 많은 진전을 이루지 못했습니다.


그만한 가치에 대해서는 아이디어 7을 사용하겠습니다. 여전히 느리지 만 다른 옵션만큼 예측할 수 없을 정도로 느리지는 않습니다. 다음 질문은 코덱 옵션, 해상도 및 키 프레임 주파수가 탐색 타이밍에 영향을 미칩니 까?
Bernt Habermeier

게임이 늦었지만 가능한 한 빨리 비디오를 전환하고 (즉, 새 비디오가 재생되기 시작한 직후) 앱을 프로파일 링하여 대부분의 CPU 시간을 소비하는 위치를 확인하는 것이 좋습니다.
tc.

1
거의 1 년 후, 이것으로 무엇을 알게 되었습니까?
lnafziger

1
나는 옵션 7로 갔고 300ms에서 500ms 사이의 어딘가에 도달했습니다. 내가 찾은 한 가지는 mp4 코덱 옵션이 더 멋질수록 seekTo가 느리다는 것입니다. 더 나은 압축을 허용하고 비디오 품질을 유지하지만 디코딩 시간을 줄이는 몇 가지 비디오 압축 옵션이 있습니다.
인 Bernt Habermeier

2
이는 합리적인 요청이지만 실제로 옵션 7을 구현하려면 게시 할 구현에 너무 많은 측면이 있습니다. 고려 사항 : (a) 비디오 자산을 병합 할 도구 체인 만들기, (b) 비디오 세그먼트 오프셋을 추적하는지 확인, (c) 특정 클립 재생 요청이 들어올 때 오프셋 조회, (d) addPeriodicTimeObserverForInterval을 사용하여 확인 비디오 클립을 실행하고 그에 따라 반응하는 경우 (이 방법과 단발 addBoundaryTimeObserverForTimes를 사용하는 경우가 있습니다. 왜냐하면 후자가 가끔 트리거되지 않기 때문입니다 ... 전반적으로 이것은 코드 붙여 넣기에 적합하지 않습니다.
Bernt Habermeier

답변:


4

iOS 10.x 이상의 경우 AVPlayer 시작 지연을 줄이기 위해 설정 avplayer.automaticallyWaitsToMinimizeStalling = false; 했습니다. 이것은 다른 결과를 초래할 수 있지만 아직 그것들을 치지 않았습니다.

https://stackoverflow.com/a/50598525/9620547 에서 아이디어를 얻었습니다.


지연 시간이 6 ~ 7 초 감소했습니다. 하지만 여기에 질문이 있습니다. 앱 성능에 영향을 미칠까요?
kalpa

@kalpa 우리는 눈에 띄는 부정적인 영향없이 1 년 넘게 프로덕션 앱에서이 코드를 사용했습니다. 일반적으로 모바일 데이터 범위가 빠른 미국의 청취자에게 20-60 분 오디오 파일을 재생합니다. 하지만 사용 사례는 다를 수 있습니다.
grizzb

정보 주셔서 감사합니다. @grizzb
kalpa

1

자산을 생성 한 후에는 준비되지 않을 수 있으며, 영화 길이와 같은 계산을 수행 할 수 있습니다. 파일에 영화의 모든 메타 데이터가 포함되어 있는지 확인하십시오.


1

옵션 # 7을 먼저 시도하여 작동 할 수 있는지 확인해야합니다. 탐색 시간이 클립 사이를 원활하게 전환 할 수있을만큼 빠르지 않을 수 있기 때문에 실제로 필요에 맞지 않을 것이라고 생각합니다. 시도했지만 실패하면 옵션 4/6을 수행하고이 목적을 위해 특별히 설계된 iOS 라이브러리를 살펴보고 AVAnimator에서 빠른 Google 검색을 수행하여 자세한 내용을 확인하는 것이 좋습니다. 내 라이브러리를 사용하면 원활한 루프를 구현하고 한 클립에서 다른 클립으로 전환 할 수 있습니다. 비디오를 미리 파일로 디코딩해야하므로 매우 빠릅니다. 귀하의 경우에는 시작하기 전에 10 개의 비디오 클립이 모두 파일로 디코딩되지만 전환이 빠릅니다.


비디오의 오디오 부분은 어떻습니까? 동기화하려면 비디오와 오디오가 필요합니다.
Bernt Habermeier 2013

예, 오디오는 이미 오디오 트랙과 비디오 클립 간의 매우 긴밀한 동기화로 처리됩니다. 예제 xcode 프로젝트를 참조하십시오. 이미 모두 구현되어 있으므로 다운로드하여 사용해보기 만하면됩니다.
MoDJ 2013

AVAnimator를 사용하여 네트워크 비디오를 재생할 수 있습니까?
리처드 Topchii

아니요, 로컬 파일에서 작동하며 네트워크 비디오 스트리밍은 완전히 다릅니다.
MoDJ

0

과거에 이와 같은 작업을 수행하지 않고 귀하의 생각과 경험을 바탕으로 7과 1의 조합을 시도해 보겠습니다. 10 개의 후속 동영상 중 처음 몇 초 동안 AVPlayer 하나를 미리로드합니다. 그러면 데이터가 적기 때문에 건너 뛰기가 더 빠르고 안정적 ​​일 수 있습니다. 선택한 곡을 재생하는 동안 백그라운드에서 선택한 나머지 후속 비디오를 위해 AVPlayer를 준비 할 충분한 시간이 있습니다. 시작이 끝나면 준비된 AVPlayer로 전환합니다. 따라서 전체적으로 주어진 시간에 최대 2 개의 AVPlayer를로드 할 수 있습니다.

물론 재생을 방해하지 않을 정도로 매끄럽게 전환 할 수 있는지는 모르겠습니다.

(가능하다면 이것을 주석으로 추가했을 것입니다.)

최고, 피터


하나의 AVPlayer에 10 개의 애셋을 시리즈로로드하는 것의 이점을 찾지 못했습니다. 또한 옵션 (1)과 (7)이 상호 배타적이라고 생각하므로 귀하의 제안을 이해하지 못합니다. 옵션 7은 모든 비디오 자산을 단일 자산으로 병합하므로로드 기간은 단일 자산 만 있습니다. 이것이 제가 오늘하고있는 일이며, 실제 시작 / 재생 시간에 약 500ms 지연이 발생하는 것이 가치있는 일입니다. SeekTo가 실제 첫 번째 프레임이 재생되는 것보다 더 빨리 완료된다는 점은 주목할 가치가 있습니다. 따라서 실제 시작 시간의 경우 첫 번째 프레임이 시간이 지정된 콜백을 통해 실제로 재생되는시기를 측정합니다.
Bernt Habermeier

내 아이디어를 명확히하기 위해 : 내 아이디어는 자산을 처음 몇 초와 나머지 두 부분으로 나누는 것이 었습니다. 이제 하나에서 두 개의 자산을 만들었습니다. 가입하고 사용하는 10 개의 시작 부분은 건너 뛰고 시작 부분을 재생하는 동안 나머지는로드합니다. 그러면 목록에 추가되는 제안 8이 포함됩니다.
ilmiacs

그러나 귀하의 마지막 의견에서 이해했듯이, 당신은 좋은 연구를 더 추진했으며 솔루션 7도 효과가 없습니다. AV가 근본적으로 당신의 방식을 방해하는 것처럼 보이며 당신이 갈 수있는 유일한 방법은 아마도 당신의 자산을 더 잘 통제하기 위해 밑에있는 기술인 Core Media를 사용하는 것입니다. 베드로.
ilmiacs

오, 이제 당신의 생각을 더 잘 이해합니다. 감사. 짧은 비디오 클립의 검색 시간이 빨라지면 조사하는 것이 흥미로울 것입니다. 나는 아직 그것을 시도하지 않았지만 고려할 가치가 있습니다. 핵심 미디어 사용과 관련하여 해당 API에 대한 좋은 참조 자료를 찾지 못했습니다. 저를 지적 할 수있는 좋은 자료가 있습니까?
Bernt Habermeier 2012 년

아니야, 미안. 제가 말했듯이 저는 AV 또는 Core Media의 전문가가 아닙니다. 귀하의 질문을 읽고 개인적으로 어떻게 진행하고 공유하고 싶은지 몇 가지 아이디어를 얻었습니다. Peter
ilmiacs

0

문제를 올바르게 이해했다면 잠시 알림을 받으면 오디오 트랙을로드해야하는 연속 동영상이 하나있는 것 같습니다.

그렇다면 BASS를 살펴 보는 것이 좋습니다. . BASS는 iOS에서 AudioUnits 프레임 워크의 저수준 API에 (상대적으로) 쉽게 액세스 할 수있는 AVPlayer와 매우 유사한 오디오 라이브러리입니다. 당신에게 어떤 의미가 있습니까? 이는 약간의 버퍼 조작으로 (필요하지 않을 수도 있으며, 원하는 지연 시간에 따라 다름) 즉시 음악 재생을 시작할 수 있음을 의미합니다.

그러나 제한 사항은 비디오로 확장됩니다. 제가 말했듯이 오디오 라이브러리이므로 모든 비디오 조작은 여전히 ​​AVPlayer로 수행해야합니다. 그러나 사용-seekToTime:toleranfeBefore:toleranceAfter: 하면 필요한 모든 옵션을 미리 적용하는 한 비디오 내에서 빠른 검색을 얻을 수 있습니다.

여러 장치에서 동기화하는 경우 (응용 프로그램에서 제안 할 수 있음) 의견을 남겨 주시면 기꺼이 답변을 수정할 수 있습니다.

추신 : BASS는 C와 같은 형식이기 때문에 처음에는 벅차게 보일지 모르지만 실제로 사용하기가 정말 쉽습니다.


-2

다음은 도움이 될 수있는 AVAsset 클래스에서 제공하는 몇 가지 속성 및 메서드입니다.

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.