在 iOS 上使用 ijkplayer 播放 RTMP, RTSP 等影音串流
最近學習如何在 iOS 裝置上播放 RTMP, RTSP 等影音串流的議題,
找了一些播放器,後來選擇使用 ijkplayer,趁還沒忘記前筆記一下。
如果環境乾淨到不能再乾淨的話,前置步驟(安裝 homebrew, git, yasm)要記得做,
接著就來建置給 iOS 的版本囉,指令的部份,我把順序記錄一下:
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
cd ijkplayer-ios
git checkout -B latest k0.7.7.1
cd config
rm module.sh
ln -s module-lite.sh module.sh
如果要播放 RTSP 到這裡先暫停一下,先用編輯器打開 module-lite.sh,
找到下面這行:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtp"
改成:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
並且在下面加上一行(不過建議放在 demuxer 那一段裡面比較好整理。):
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
存檔後繼續您的終端機:
cd ..
./init-ios.sh
cd ios
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
接著就等他編譯完成了。
完成後我們來測試一下 RTSP, RTMP 是否可以正常播放,
我們打開 IJKMediaDemo 專案,如下圖位置:
修改 IJKDemoInputURLViewController.m 檔案,
找到:
- (void)onClickPlayButton {
NSURL *url = [NSURL URLWithString:self.textView.text];
NSString *scheme = [[url scheme] lowercaseString];
if ([scheme isEqualToString:@"http"]
|| [scheme isEqualToString:@"https"]
|| [scheme isEqualToString:@"rtmp"]) {
改成:
- (void)onClickPlayButton {
NSURL *url = [NSURL URLWithString:self.textView.text];
NSString *scheme = [[url scheme] lowercaseString];
if ([scheme isEqualToString:@"http"]
|| [scheme isEqualToString:@"https"]
|| [scheme isEqualToString:@"rtsp"]
|| [scheme isEqualToString:@"rtmp"]) {
改好以後就在模擬器裡跑跑看:
點選 Input URL 填入要測試的 url,
RTMP 基本上是沒問題,主要是 RTSP 要測測看,
走 UDP 的應該沒問題可以正常播放,如果是 TCP 的,要設 option,後面會提到。
接著我們要把 IJKMediaFramework 拿來用,
參考:Swift - 使用ijkplayer框架播放直播视频1(RTMP/HTTP视频流播放)
自己操作記錄如下:
使用 Xcode 開啟 IJKMediaPlayer.xcodeproj
點擊左上角的 IJKMediaFramework 選擇 Edit Scheme...
接著將 Build Configuration 改為 Release
按下 Close
選擇一個模擬器,按下 Build(command + B)
改選 Generic iOS Device 一樣按下 Build(command + B)
然後可以看到 IJKMediaFramework.framework 由紅色變成黑色了,
這時候去看看他的目錄
我們可以發現有兩個目錄,一個是給實機使用,另一個是給模擬器使用
我們使用 lipo 指令將兩個 framework 合併
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
cp IJKMediaFramework Release-iphoneos/IJKMediaFramework.framework/
另外可以參考 Clark 大大的文章 [iOS] 建立與使用Framework 直接寫成 Script 方便使用,
不過合併這件事我們應該只會用一次,就沒做嘗試了。
接著我們新增一個 Single View Application 專案 rtspdemo,
先把必要的 Library 加進來
再把先前做好的 framework 拉進來
勾選 Copy items if needed
接著我們在 ViewController.swift 來寫播放的程式了(程式碼範例引用自Swift - 使用ijkplayer框架播放直播视频1(RTMP/HTTP视频流播放)),
但 Swift 3 語法稍有不同,按照 Xcode 提示修改即可。
import UIKit
import IJKMediaFramework
class ViewController: UIViewController {
var player: IJKFFMoviePlayerController!
override func viewDidLoad() {
super.viewDidLoad()
// 參數設定
let options = IJKFFOptions.byDefault()
// URL
let url = URL(string: "填入你的 rtmp/rtsp url 測試吧!")
// 初始化
let player = IJKFFMoviePlayerController(contentURL: url, with: options)!
// 自動調整寬高
let autoresize = UIViewAutoresizing.flexibleWidth.rawValue |
UIViewAutoresizing.flexibleHeight.rawValue
player.view.autoresizingMask = UIViewAutoresizing(rawValue: autoresize)
player.view.frame = self.view.bounds
// 縮放模式
player.scalingMode = IJKMPMovieScalingMode.aspectFit
// 自動播放
player.shouldAutoplay = true
// 設定 sub view 自動調整
self.view.autoresizesSubviews = true
self.view.addSubview(player.view)
self.player = player
// 開始播放
self.player.prepareToPlay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// 停止播放
self.player.shutdown()
}
}
到這邊就大功告成啦!
另外,前面有提到,如果 RTSP 是走 TCP 的話,需要調整一下參數。
修改方式如下:
// 參數設定
let options = IJKFFOptions.byDefault()
// 使用 TCP
options?.setOptionValue("tcp", forKey: "rtsp_transport", of: IJKFFOptionCategory(1))
如果需要使用硬解的話可以調整如下:
// 參數設定
let options = IJKFFOptions.byDefault()
// 使用 TCP
options?.setOptionValue("tcp", forKey: "rtsp_transport", of: IJKFFOptionCategory(1))
// 使用硬解
options?.setPlayerOptionIntValue(1, forKey: "videotoolbox")
編譯環境:
macOS: 10.12.3
Xcode: 8.2.1
以上內容如有錯誤的地方,請多包含,並提醒小弟我,謝謝!
文章參考引用出處:
1. Bilibili/ijkplayer GitHub
2. I'm can't play video with rtsp
3. iOS用ijkplayer播RTSP流
4. Swift - 使用ijkplayer框架播放直播视频1(RTMP/HTTP视频流播放)
5. [iOS] 建立與使用Framework
6. 在xcode8.2.1跑不了,有人遇到吗?
7. How to force rtsp streaming using TCP mode?
8. 将rtsp流强制改成tcp