BiliBili(簡稱B站),想必大家都不陌生。Ijkplayer 框架是B站提供了一個開源的流媒體解決方案,集成了 ffmpeg,還支持硬解碼(需 iOS8 以上版本)。使用 Ijkplayer 框架我們可以很方便地實現視頻直播功能(Http/RTMP/RTSP 這幾種直播源都支持)。
本文主要介紹如何使用 Ijkplayer 框架播放在線直播視頻(當然其本地播放能力也很強大)。對於幾種直播流不太清楚地,可以參考我前面寫的這篇文章:RTMP、RTSP、HTTP視頻協議詳解(附:直播流地址、播放軟件)
一,環境部署
在使用 Ijkplayer 前,我們需要先搭建運行環境。
1,在“終端”中運行如下命令,安裝homebrew, git, yasm等環境。
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install git
brew install yasm
2,將Ijkplayer項目下載到本地
GitHub地址:https://github.com/Bilibili/ijkplayer
或者在“終端”中使用 git 命令下載到本地:
1
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
3,將ffmpeg集成到ijkplayer中
運行如下命令,進入項目文件夾並集成 ffmpeg。
cd ijkplayer-ios
git checkout -B latest k0.6.0
./init-ios.sh
cd ios
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
二、運行樣例
Ijkplayer 工程目錄中自帶了一個 demo 樣例,我們可以先運行下看看效果。
1,打開ios文件夾下的IJKMediaDemo工程
2,運行後界面如下
可以選擇播放本地文件,或者輸入視頻地址來播放。同時 demo 中還自帶了一些視頻源,可以直接點擊播放。
3,在Input URL頁面中輸入視頻地址即可播放
不過程序默認做了限制,只能播放 http/https 視頻流。
我們這裡可以修改下,放開限制。讓其也能支持其它協議視頻播放(比如 RTMP 協議)。
將 IJKDemoInputURLViewController.m 中的相關判斷給注釋掉即可。
1
//if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
[IJKVideoViewController presentFromViewController:self withTitle:[NSString stringWithFormat:@"URL: %@", url] URL:url completion:^{
// [self.navigationController popViewControllerAnimated:NO];
}];
//}
三、將Ijkplayer集成到我們的項目中來
下面我們通過一個樣例演示在我們項目中如何通過 ijkplayer 來播放視頻流。官方提供的 demo 用的是 OC,這裡我使用 Swift 來實現。
1,制作framework
首先我們要將 IJKMediaPlayer 編譯成 framework,這樣不僅體積小,而且使用起來也更加方便。
(1)打開 IJKMediaPlayer.xcodeproj(ios/IJKMediaPlayer 文件夾下)
(2)點擊 IJKMediaFramework 出現選擇框,選擇 edit scheme
(3)將 build configuration 改為 Release
(4)分別在模擬器和真機(Generic iOS Device 也可以)上編譯
(5)我們打開生成 framework 的目錄
(6)可以看到這裡生成了兩個 framework。看名字就知道一個是給模擬器使用,一個是給真機使用。這個根據個人的運行需求選擇對應的 framework。
原文:Swift - 使用ijkplayer框架播放直播視頻1(RTMP/HTTP視頻流播放)
(7)當然如果在開發階段,真機模擬器都需要調試這樣切來切去就太麻煩了。我們將兩個 framework 合並,這樣就可以同時在真機和模擬器上調試了。
我們進入 Products 目錄,輸入如下 lipo 命令將二者合並輸出:
1
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
(8)接著將合並後的 framework 拷貝到 Release-iphoneos/IJKMediaFramework.framework 中
1
cp IJKMediaFramework Release-iphoneos/IJKMediaFramework.framework/
(9)我們可以通過 lipo -info IJKMediaFramework 命令查看 framework 支持情況。可看到現在這個真機、模擬器都是支持的。
原文:Swift - 使用ijkplayer框架播放直播視頻1(RTMP/HTTP視頻流播放)
2,項目配置
(1)我們將前面制作好的 framework(Release-iphoneos/IJKMediaFramework.framework)添加到我們項目中來。
(2)接著添加一些依賴的動態庫。
AudioToolbox.framework
AVFoundation.framework
CoreGraphics.framework
CoreMedia.framework
CoreVideo.framework
libbz2.tbd
libz.tbd
MediaPlayer.framework
MobileCoreServices.framework
OpenGLES.framework
QuartzCore.framework
UIKit.framework
VideoToolbox.framework
原文:Swift - 使用ijkplayer框架播放直播視頻1(RTMP/HTTP視頻流播放)
四、測試樣例
項目配置完畢後,接下來寫一個簡單的樣例演示如何使用 ijkplayer。
1,樣例效果圖
程序啟動後會自動播放一個采用 RTMP 協議的直播,並全屏顯示。
原文:Swift - 使用ijkplayer框架播放直播視頻1(RTMP/HTTP視頻流播放)
同時播放視圖會自適應手機橫、豎兩種狀態。
原文:Swift - 使用ijkplayer框架播放直播視頻1(RTMP/HTTP視頻流播放)
2,樣例代碼
import UIKit
import IJKMediaFramework
class ViewController: UIViewController {
var player:IJKFFMoviePlayerController!
override func viewDidLoad() {
super.viewDidLoad()
let options = IJKFFOptions.optionsByDefault()
//視頻源地址
let url = NSURL(string: "rtmp://live.hkstv.hk.lxdns.com/live/hks")
//let url = NSURL(string: "http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8")
//初始化播放器,播放在線視頻或直播(RTMP)
let player = IJKFFMoviePlayerController(contentURL: url, withOptions: options)
//播放頁面視圖寬高自適應
let autoresize = UIViewAutoresizing.FlexibleWidth.rawValue |
UIViewAutoresizing.FlexibleHeight.rawValue
player.view.autoresizingMask = UIViewAutoresizing(rawValue: autoresize)
player.view.frame = self.view.bounds
player.scalingMode = .AspectFit //縮放模式
player.shouldAutoplay = true //開啟自動播放
self.view.autoresizesSubviews = true
self.view.addSubview(player.view)
self.player = player
}
override func viewWillAppear(animated: Bool) {
//開始播放
self.player.prepareToPlay()
}
override func viewWillDisappear(animated: Bool) {
//關閉播放器
self.player.shutdown()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}