50

ios 基于FreeStreamer的流媒体播放器,实现歌词同步及锁屏控制

 5 years ago
source link: http://www.cocoachina.com/ios/20190409/26759.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

简介

使用FreeStreamer实现了一个流媒体播放器,同时还实现了歌词同步,锁屏控制,歌曲切换,后台自动播放等功能。

演示效果

VbaEJze.gif

总览.gif

附上项目地址 chenfengxiaoxixi

实现技术点及流程

1.单例

首先播放器所在controller我是使用单例初始化的,不然pop到上一级控制器后,当前对象释放掉,就无法播放了

+ (instancetype)sharePlayerController
{
    static CFPlayerController *_instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

这个方法是线程安全的。

2.歌词同步

VJRZjuB.gif

歌词同步.gif

这里重点是歌词格式的问题,才开始我用的纯歌词文本,很难精确定位到播放到哪段歌词了,后来网上查了下资料,才知道用lrc格式的歌词定位,格式:[时间]+歌词,如下

[00:21.70]客官里面请几位
[00:24.72]请上座好茶来奉陪
[00:27.71]一双筷从南吃到北
[00:30.73]中华五千年留下的韵味

分别用数组把时间和歌词文本存下来,然后用tableview显示出来。在播放进度里面,用正在播放的时间和歌词文本的时间段对比,然后标记当前正在播放哪段歌词。

3.后台持续播放

先在xcode配置里面(TARGETS->Capabilities)打开Background Modes,勾选上Audio那一栏。现在只是满足了后台播放条件,要想连续不断在后台播放,还要申请后台任务id。

//添加后台播放任务
    UIBackgroundTaskIdentifier bgTask = 0;
    if([UIApplication sharedApplication].applicationState== UIApplicationStateBackground) {

        NSLog(@"后台播放");

       UIApplication*app = [UIApplication sharedApplication];

        UIBackgroundTaskIdentifier newTask = [app beginBackgroundTaskWithExpirationHandler:nil];

        if(bgTask!= UIBackgroundTaskInvalid) {

            [app endBackgroundTask: bgTask];
        }

        bgTask = newTask;
        [self next];
    }
    else {

        NSLog(@"前台播放");
        [self.cdView scrollRightWIthNext];

    }

播放完成一首歌后,这段代码用来判断当前处于前台还是后台,如果是后台,那就申请后台任务继续播放下一首。

4.锁屏后对音乐播放的操作及信息显示

namyEvu.gif

锁屏演示.gif

这里我使用的MPRemoteCommandCenter实现的功能,不过该类的部分方法只支持ios9.1版本以上。

配置要实现的操作

- (void)configRemoteControlEvents
{
//    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    //初始化远程控制中心
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

    if (@available(iOS 9.1, *)) {

        //播放,暂停
        [commandCenter.togglePlayPauseCommand addTarget:self action:@selector(remoteControlActionWithPlayPause:)];
        //下一首
        [commandCenter.nextTrackCommand addTarget:self action:@selector(remoteControlActionWithNext:)];
        //上一首
        [commandCenter.previousTrackCommand addTarget:self action:@selector(remoteControlActionWithPre:)];
        //进度条拖动
        [commandCenter.changePlaybackPositionCommand addTarget:self action:@selector(remoteControlActionSeekToPosition:)];
    } else {
        // Fallback on earlier versions
    }

}

更新锁屏后音乐的显示信息

//锁屏显示信息


- (void)configNowPlayingInfoCenter
{
    if (NSClassFromString(@"MPNowPlayingInfoCenter")) {

        NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];

        [dict setObject:CFUSER.currentSongModel.songName forKey:MPMediaItemPropertyTitle];

        [dict setObject:@(self.playTime) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
        //音乐的总时间
        [dict setObject:@(self.totalTime) forKey:MPMediaItemPropertyPlaybackDuration];
        //当前歌词添加在副标题处
        if (_lyricsManager.currentRow <= _lyricsManager.textArray.count - 1) {
            [dict setObject:_lyricsManager.textArray[_lyricsManager.currentRow] forKey:MPMediaItemPropertyAlbumTitle];
        }

        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];

    }
}

5.关于FreeStreamer的使用

初始化,开始播放

//初始化播放器
- (void)buildStreamer
{
    weakSELF;
    // 网络文件
    NSURL *url = [NSURL URLWithString:CFUSER.currentSongModel.url];

    if (!_audioStream) {

        // 创建FSAudioStream对象
        _audioStream = [[FSAudioStream alloc] initWithUrl:url];
        _audioStream.onFailure = ^(FSAudioStreamError error,NSString *description){
            NSLog(@"播放过程中发生错误,错误信息:%@",description);

            [weakSelf showAlertMsg:description];

        };
        _audioStream.onCompletion=^(){

            [weakSelf autoPlayNext];
        };

        [_audioStream preload];
        [_audioStream play];
    }

}

停止播放

[self.audioStream stop];

暂停播放和继续播放为同一个方法

[self.audioStream pause];

拖动进度条播放

- (void)dragSliderEnd:(UISlider *)slider{
    //滑动到底时,播放下一曲
    if (slider.value == 1) {
         [self.cdView scrollRightWIthNext];
    }
    else
    {
        if (slider.value > 0)
        {
            //初始化一个FSStreamPosition结构体
            FSStreamPosition pos;
            //只对position赋值,value由slider控制
            pos.position = slider.value;
            [self.audioStream seekToPosition:pos];// 到指定位置播放
        }
    }
}

结语

以上实现了一个简单的流媒体音乐播放器,代码里面有比较详细的注释,想看详细实现流程和源码的可以去我的项目查看。

戳这里 chenfengxiaoxixi


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK