Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

音视频 #13

Open
ShannonChenCHN opened this issue Apr 23, 2017 · 5 comments
Open

音视频 #13

ShannonChenCHN opened this issue Apr 23, 2017 · 5 comments

Comments

@ShannonChenCHN
Copy link
Owner

ShannonChenCHN commented Apr 23, 2017

  • 视频
    • 视频格式
    • 视频编码解码
    • 视频文件播放
    • 在线视频播放
    • 视频编辑
  • 音频
    • 音频格式
    • 音频文件播放
    • 在线音频播放
    • 录音
    • 语音识别
    • 音频处理
  • 其他
    • 耳机线路
    • 中断处理
@ShannonChenCHN ShannonChenCHN changed the title 【专题】视频播放 【收藏夹】视频播放 Apr 23, 2017
@ShannonChenCHN ShannonChenCHN changed the title 【收藏夹】视频播放 【专题】视频播放 Apr 26, 2017
@ShannonChenCHN ShannonChenCHN changed the title 【专题】视频播放 【专题】视频 Apr 27, 2017
@ShannonChenCHN ShannonChenCHN changed the title 【专题】视频 视频 Dec 14, 2017
@ShannonChenCHN
Copy link
Owner Author

ShannonChenCHN commented Dec 14, 2017

AVPlayer 相关

1. 如何停止播放?

AVPlayer 没有 stop 方法,我们可以调用 pause 方法,或者设置 rate 为 0。
如果需要回到起点,可以设置进度并暂停:

[self.videoPlayer seekToTime:CMTimeMake(0, 1)];
[self.videoPlayer pause];

参考:

2. 针对下载再播的小视频,如何实现视频的下载和缓存逻辑?

可以参考 SDWebImage 的实现,不同的地方在于,这里没有内存缓存,因为 AVPlayer 是直接从磁盘上加载文件的,如果要做优化的话,可以将每个 URL 对应的 AVURLAsset 对象缓存起来:

  • 先从读取缓存,如果缓存存在,则根据缓存路径播放视频
  • 如果没有缓存,就使用 NSURLSession 进行下载,下载结束后保存到缓存目录,保存完成后,再根据缓存路径播放视频

3. 如果要实现一个边下边播的播放器?该如何实现?

参考:

4. 当使用 AVPlayer 播放视频被来电铃声、闹钟铃声打断时,如何恢复播放?

iOS 6以后,可以通过处理 AVAudioSessionInterruptionNotificationAVAudioSessionMediaServicesWereResetNotification 这两个通知来实现监控。

首先,设置 AVAudioSession

AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setCategory:AVAudioSessionCategoryPlayback
          withOptions:AVAudioSessionCategoryOptionAllowBluetooth 
                error:&error];
[aSession setMode:AVAudioSessionModeDefault error:&error];
[aSession setActive: YES error: &error];

然后,注册通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleAudioSessionInterruption:)
                                             name:AVAudioSessionInterruptionNotification
                                           object:aSession];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleMediaServicesReset)
                                             name:AVAudioSessionMediaServicesWereResetNotification
                                           object:aSession];

最后,处理终端通知:

- (void)handleAudioSessionInterruption:(NSNotification*)notification {

    NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey];
    NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];

    switch (interruptionType.unsignedIntegerValue) {
        case AVAudioSessionInterruptionTypeBegan:{
            // • Audio has stopped, already inactive
            // • Change state of UI, etc., to reflect non-playing state
        } break;
        case AVAudioSessionInterruptionTypeEnded:{
            // • Make session active
            // • Update user interface
            // • AVAudioSessionInterruptionOptionShouldResume option
            if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
                // Here you should continue playback.
                [player play];
            }
        } break;
        default:
            break;
    }
}

5. 如何实现后台播放 AVPlayer?

6. 针对播放线路(耳机、扬声器)改变的响应

7. 如何实现播放视频时,不中断其他应用中正在播放的音频?

答:可以通过设置 AVAudioSession 单例的 category 和 option 来实现,代码如下:

// 方式一:AVAudioSessionCategoryPlayback + AVAudioSessionCategoryOptionMixWithOthers
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
                                     withOptions:AVAudioSessionCategoryOptionMixWithOthers
                                           error:nil];
// 方式二:AVAudioSessionCategoryAmbient
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error:nil];

Audio Session 是什么?

系统通过 audio sessions 来管理 app 级、app 间和系统级的音频播放、录制行为。我们可以在 app 中通过使用 audio sessions 来告诉系统,我们需要怎样配置音频服务。

Audio Session 的 category 和 mode、options ?

配置 Audio Session 行为的三个层级,最基本的是 category,在 category 的基础上可以通过设置 mode 和 category 来进行“微调”。

参考:

8. 如何知道 AVPlayer 是否正在播放?

可以通过判断 AVPlayer 的 rate 属性值是否不为 0 来判断:

AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
    // player is playing
}

参考:

@ShannonChenCHN
Copy link
Owner Author

ShannonChenCHN commented Dec 14, 2017

如何实现在列表中播放多个视频的同时,保证滚动的流畅性?

我自己是使用 AVPlayer 在列表中显示视频的,发现在一开始加载时会比较卡,在需要展示的 cell 都初始化完后,就明显流畅多了。
profile 工具查看
查了一下资料,有提到

参考:

@ShannonChenCHN
Copy link
Owner Author

iOS 上播放视频的几种方式

@ShannonChenCHN ShannonChenCHN changed the title 视频 音视频 Jan 16, 2018
@ShannonChenCHN
Copy link
Owner Author

ShannonChenCHN commented Feb 2, 2018

如何判断一个视频文件是否可以播放?

方式一:通过监听 AVPlayer 或者 AVPlayerItem 的 status 来判断。值得注意的是,如果你直接在初始化 AVPlayer 之后就同步获取这个值,这个值会是 “unknown”。

        avplayer = AVPlayer(url: url)
        avplayer.addObserver(self, forKeyPath: "status", options: .new, context: nil)
...
...

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if (avplayer == object as? AVPlayer) && (keyPath == "status") {
            print((avplayer.status == .readyToPlay) ? "readyToPlay" : "fail")
        }
    }

方式二:直接通过 url 新建一个 AVAsset 对象,再通过 isPlayable 属性判断视频是否可以正常播放。

        let avasset = AVAsset(url: url)
        print(avasset.isPlayable)

结论:

方法一是异步,方法二是同步。方法二比方法一要快了将近一倍。

参考:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant