webrtcのObj-Cポーティングもそろそろ落ち着いてきた(?)頃合いなので、iOSの実機にWebRTCを組み込んでみます。 本記事中でSVNのバージョンは http://webrtc.googlecode.com/svn/trunk のr7864を使用しています。
この記事でも書きましたが、webrtcのiOSビルドは、 How to get started with WebRTC and iOS without wasting 10 hours of your life ↑この記事が親切かつ、まめにアップデートされているのでオススメです。
ですが、忙しい人のためにコマンドだけざっくり列挙してみます。
ワーキングディレクトリは~/webrtc
としています。
cd ~/webrtc
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:$PATH
gclient config --name src http://webrtc.googlecode.com/svn/trunk
echo "target_os = ['ios']" >> .gclient
gclient sync --force
export GYP_GENERATORS="ninja"
export GYP_DEFINES="build_with_libjingle=1 build_with_chromium=0 libjingle_objc=1 OS=ios target_arch=armv7"
export GYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGS output_dir=out_ios"
export GYP_CROSSCOMPILE=1
pushd src
gclient runhooks
ninja -C out_ios/Release-iphoneos AppRTCDemo
popd
libtool -static -o src/out_ios/Release-iphoneos/libWebRTC-ios.a src/out_ios/Release-iphoneos/*.a
strip -S -x -o src/out_ios/Release-iphoneos/libWebRTC-ios-min.a -r src/out_ios/Release-iphoneos/libWebRTC-ios.a
cp src/out_ios/Release-iphoneos/libWebRTC-ios-min.a .
cp -r src/third_party/libjingle/source/talk/app/webrtc/objc/public .
ビルドに大体30分ぐらい掛かると思います。
コマンドの最後で今回組み込むlibWebRTC-ios-min.a
とObjective-Cヘッダのpublic
ディレクトリをカレントディレクトリに持ってきています。
なかなかスムーズにはいかないと思うので個人的にハマった所を少し説明します。
普通はProfileを複数管理している事が多いと思うので、↓のエラーが出るかもしれません。
AssertionError: Multiple codesigning fingerprints for identity: iPhone Developer
これもこの記事の中で詳しく解説してあります。
- 手っ取り早い対処法
src/build/common.gypi
にあるiPhone Developer
を空文字にします。
'iPhone Developer' -> ''
Xcodeを同じディレクトリにバックアップしていたりすると良くあるパターンです。
- 対処法
必要に応じてXcode.appのパスを変更して、下記コマンドを叩いて修正します。
$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
ライブラリがビルド出来れば後は組み込むだけです。
適当にXcodeでiOSアプリプロジェクトを立ち上げて、先ほど作ったlibWebRTC-ios-min.a
とpublic
を放り込みます。
Linked Frameworks and Libraries
に依存しているフレームワークを追加します。
libstdc++.dylib
libicucore.dylib
GLKit.framework
libsqlite3.0.dylib
AVFoundation.framework
libWebRTC-ios-min.a
注意点として、libWebRTC-ios-min.a
はarmv7のライブラリになっているためValid Architectures
をarmv7だけにする必要が有ります。
また、Build Active Architectures
もNO
にしておいてください。
(Cocoapodsのライブラリに対してこの設定を一括で適用する際はこの記事も参考にしてみてください。)
ここまででビルドが通ったら、おもむろにローカルストリームでフロントカメラの映像を出してみましょう。
適当なUIViewControllerのviewDidLoad
あたりで次のようなコードを入れます。
#import <AVFoundation/AVFoundation.h>
#import "RTCEAGLVideoView.h"
#import "RTCMediaStream.h"
#import "RTCPeerConnectionFactory.h"
#import "RTCMediaConstraints.h"
#import "RTCPeerConnection.h"
#import "RTCPair.h"
#import "RTCVideoCapturer.h"
#import "RTCVideoTrack.h"
#import "RTCAudioTrack.h"
#import "RTCICECandidate.h"
#import "RTCSessionDescription.h"
#import "ViewController.h"
@implementation ViewController {
RTCMediaStream *_local_media_stream;
RTCPeerConnection *_peer;
}
- (void)viewDidLoad
{
[super viewDidLoad];
RTCPeerConnectionFactory *pc_factory = [RTCPeerConnectionFactory new];
_peer = [pc_factory peerConnectionWithICEServers:nil constraints:nil delegate:nil];
RTCEAGLVideoView * local_view = [[RTCEAGLVideoView alloc] initWithFrame:self.view.frame];
[self.view addSubview:local_view];
_local_media_stream = [pc_factory mediaStreamWithLabel:@"ARDAMS"];
NSString *camera_id = nil;
for (AVCaptureDevice *dev in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] ) {
if (dev.position == AVCaptureDevicePositionFront) {
camera_id = [dev localizedName];
break;
}
}
RTCVideoCapturer *capturer = [RTCVideoCapturer capturerWithDeviceName:camera_id];
RTCVideoSource *source = [pc_factory videoSourceWithCapturer:capturer constraints:nil];
RTCVideoTrack *video_track = [pc_factory videoTrackWithID:@"ARDAMSv0" source:source];
[_local_media_stream addVideoTrack:video_track];
[video_track addRenderer:local_view];
}
@end
ここでは基本的にWeb APIのgetUserMedia
でvideoタグのsrc
を設定しているのと同じ事をしています。
Obj-CのAPIもWeb APIと大体同じなので、それほど苦労せずに後は実装していけるのではないかと思います。
(ちなみに画面サイズは適当です)
ここまでの時点のXcodeプロジェクトを上げてあります。参考にどうぞ。
いつもの如くWebRTCではシグナリングサーバーとICEサーバーを別途用意しないと満足に遊べないという独特の面倒くささがありますが、 ここでふと思い直してみると、
- iOSアプリは普通にhttp/websocketサーバーとして使う事が出来る (CocoaHTTPServer etc.)
- LANではICEサーバーが要らない (自分自身がICE Candidateになるため)
というわけで、実はiOSアプリが一つあればLAN上にビデオチャットサービスを展開する事が出来ます。 Androidではやった事が無いですが、そっちも同じようにいけると思います。
LANだけという制限は有りますが、サーバーとピアを統合することで何か面白いアプリが作れるかもしれません。 _機会があれば_サーバー組み込みバージョンも記事にしようと思います。機会があれば。