Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ビデオ通話アプリのお話
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
taminif
April 22, 2017
Programming
3
540
ビデオ通話アプリのお話
Skywayサービスを利用して、iOSでWebRTCを実装した話です。
taminif
April 22, 2017
Tweet
Share
More Decks by taminif
See All by taminif
React Native New Architecture 移行実践報告
taminif
1
210
「とりあえずAI」が招く悲劇〜私がAIで生産性を下げるまでの話〜 / The tragedy caused by "AI for now" - The story of how I used AI to reduce my productivity
taminif
1
280
PuppeteerとPlaywrightの15日間の演劇 / relation of Puppeteer and Playwright
taminif
3
2.3k
Redashの開発はじめました / How to get started Redash development
taminif
0
790
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
530
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
6.1k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.6k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
1k
オンライン英会話とSkyWay
taminif
0
540
Other Decks in Programming
See All in Programming
DSPy入門 Pythonで実現する自動プロンプト最適化 〜人手によるプロンプト調整からの卒業〜
seaturt1e
1
730
PostgreSQL を使った快適な go test 環境を求めて
otakakot
0
550
Claude Codeログ基盤の構築
giginet
PRO
7
3.3k
CSC307 Lecture 14
javiergs
PRO
0
470
メタプログラミングで実現する「コードを仕様にする」仕組み/nikkei-tech-talk43
nikkei_engineer_recruiting
0
190
文字コードの話
qnighy
44
17k
Goの型安全性で実現する複数プロダクトの権限管理
ishikawa_pro
2
330
モダンOBSプラグイン開発
umireon
0
120
米国のサイバーセキュリティタイムラインと見る Goの暗号パッケージの進化
tomtwinkle
2
580
maplibre-gl-layers - 地図に移動体たくさん表示したい
kekyo
PRO
0
270
AI 開発合宿を通して得た学び
niftycorp
PRO
0
120
nilとは何か 〜interfaceの構造とnil!=nilから理解する〜
kuro_kurorrr
3
1.9k
Featured
See All Featured
The Curse of the Amulet
leimatthew05
1
10k
Odyssey Design
rkendrick25
PRO
2
540
Unsuck your backbone
ammeep
672
58k
Prompt Engineering for Job Search
mfonobong
0
180
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
640
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
The World Runs on Bad Software
bkeepers
PRO
72
12k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
71
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
200
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.1k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.4k
How to build a perfect <img>
jonoalderson
1
5.3k
Transcript
ϏσΦ௨ΞϓϦͷ͓ Cocoaษڧձؔ #72 2017/04/22 େౡ ޫو@taminif
ࣗݾհ • ΣϒϦΦגࣜձࣾWEBΤϯδχΞ • ΞϓϦΤϯδχΞ ʢࣗশʣ • ࠓͷͨΊʹ ͍͖͖ͭͬͬͯ͞·ͨ͠ʂ
Weblio ͝ଘͰ͔͢ʁ
http://ejje.weblio.jp/content/Cocoa?dictCode=WEJTY
ΦϯϥΠϯࣙॻΛఏڙ͢Δ WebαʔϏε
࣮ࣙॻҎ֎ʹ ͜ΜͳαʔϏεΛ͍ͬͯ ·͢
https://eikaiwa.weblio.jp/
ΦϯϥΠϯӳձαʔϏε
Skypeӳձͱݴ͑ ฉ͍ͨ͜ͱ͋Δํ ଟ͍ͷͰͳ͍Ͱ͠ΐ͏͔
ͦΜͳWeblioӳձͰ͕͢
ʂ
3݄1ΑΓɺWebRTCΛ ༻ͨ͠Ϩοεϯʹ Ҡߦ͠·ͨ͠ɻ
WebRTCͱ • W3C͕ఏএ͢ΔP2PϦΞϧλΠϜίϛϡχέʔ γϣϯΛ࣮ݱ͢Δٕज़ • ϓϥάΠϯͳ͠ͰϒϥβؒͷΓͱΓ͕Մೳ • ຊΈʹ͍ͭͯৄ͘͠Γ·ͤΜʂ ->αʔό͕ඞཁͰͦ͠͏ʹݟ͑·͕͢ ͜ΕΒΛఏڙ͢ΔαʔϏε͕͋Γ·͢ʂ
WebRTCΛ؆୯ʹ࣮ݱ͢Δ αʔϏε ొ͢ΕແྉͰ༻Մೳʂ https://nttcom.github.io/skyway/
֤ϒϥβରԠঢ়گʢPCʣ • Google Chrome • Firefox • Opera • Edge(Creators
UpdateͰରԠ༧ఆ) • Safari(ରԠத) ※࠷৽όʔδϣϯΛର
֤ϒϥβରԠঢ়گʢεϚϗʣ • Android -> ChromeରԠࡁΈʢͦͷଞະݕূʣ • iOS -> ඇରԠɾɾɾ
iPhoneiPadͰ Weblioӳձ͕͑ͳ͍
None
มΘͬͯɺ Weblioӳձֶߍ اۀʹఏڙ͍ͯ͠·͢
·ͨɺֶߍͷதʹ iPadΛतۀʹ༻͢Δॴ ૿͖͑ͯ·ͨ͠
ʮWeblioӳձΛiPadͰ ༻Ͱ͖ͳ͍ʁʯ
None
͔͜͜Β͕ຊͰ͢
ʮiOSΞϓϦʹWebRTCΛ ࣮ͨ͠ʯ
https://itunes.apple.com/jp/app/weblio๏ਓӳձ/id1215209006?mt=8
ϦϦʔε͠·ͨ͠
SkyWayΛͬͯ ϏσΦΞϓϦΛ࣮ͨ͠ ݟΛڞ༗͠·͢
1. ಋೖฤ
ωΠςΟϒΞϓϦ༻ͷ SDKΛՃ͠·͢
ެ͔ࣜΒϥΠϒϥϦ͕ https://webrtc.org/native-code/ios/
SkyWayͰϥΠϒϥϦ͕ ʢϥοϐϯάͨ͠ϥΠϒϥϦʣ https://nttcom.github.io/skyway/documentation.html
SkyWay iOS SDK • αΠτ͔Βμϯϩʔυ or GithubͰclone or CocoaPodsͰΠϯετʔϧ •
Objective-CͰॻ͔Ε͍ͯΔͷͰ Bridging-HeaderΛՃͯ͠ಡΈࠐΈ
ͦͷଞɺ͍͔ͭ͘ frameworkΛಡΈࠐΉඞཁ ͕͋Γ·ׂ͕͢Ѫ ʢެࣜͷυΩϡϝϯτࢀরʣ
2. νϟωϧฤ
ೋͭͷνϟωϧ • ϝσΟΞνϟωϧ ө૾ԻͷStreamΛΓͱΓ͢Δνϟωϧ • σʔλνϟωϧ ςΩετόΠφϦσʔλΛΓͱΓ͢Δ νϟωϧ
SkyWayͰ mediaConnectionΫϥεͱ dataConnectionΫϥε
Connectionʹ StreamσʔλΛͯ͠ ΓͱΓ͠·͢
ϏσΦ௨ʹϝσΟΞνϟ ωϧΛ༻͠·͢
mediaConnection // ૬खͷϝσΟΞνϟωϧΛड͚औΔCALLBACKΛઃఆ peer?.on(SKWPeerEventEnum.PEER_EVENT_CALL, callback: {(obj) -> Void in let
mediaConnection:SKWMediaConnection = obj as! SKWMediaConnection mediaConnection.answer(self.localMediaStream) }) ※্هҎ֎ʹpeer.callWithId(callId, localStream)Ͱ૬खʹͭͳ͙͜ͱ͕Ͱ͖Δ
mediaConnectionʹ localStreamΛ͠ remoteStreamΛ ड͚औΓ·͢
localStreamΛऔಘ // peerΠχγϟϥΠζ SKWNavigator.initialize(peer) // constraintsઃఆ let constraints:SKWMediaConstraints = SKWMediaConstraints.init()
// ΧϝϥϞʔυઃఆ constraints.cameraMode = .CAMERA_MODE_ADJUSTABLE // ΧϝϥͷҐஔઃఆ constraints.cameraPosition = .CAMERA_POSITION_FRONT // localMediaStreamऔಘ localMediaStream = SKWNavigator.getUserMedia(constraints)
remoteStreamΛऔಘ // MediaConnectionͷCALLBACKΛઃఆ mediaConnection.on(SKWMediaConnectionEventEnum.MEDIACONNECTION_EVENT _STREAM, callback: {(obj) -> Void in
self.remoteMediaStream = obj as? SKWMediaStream DispatchQueue.global(qos: .default).async { let remoteVideo:SKWVideo = self.view.viewWithTag(1002) as! SKWVideo remoteVideo.isUserInteractionEnabled = true remoteVideo.addSrc(self.remoteMediaStream, track: 0) } })
͓ͬͯ͘͜ͱ
ΧϝϥͱϚΠΫͷڐՄΛऔΔ • Info.plistʹઆ໌จΛ༻ҙ͢Δ • ༻ҙͨ͠จ͕σόΠεڐՄऔಘ࣌ʹදࣔ͞ΕΔ • NSCameraUsageDescription • NSMicrophoneUsageDescription •
ΧϝϥͱϚΠΫͷڐՄΛऔΔ • AVCaptureDevice • Χϝϥ͕༻ෆՄͩͱgetUserMedia͕ࣦഊ͢Δ͕ɺ ϚΠΫ͕༻ෆՄͰgetUserMediaࣦഊ͠ͳ͍ • ϚΠΫσόΠεͷΓସ͑Ͱ͖ͳ͍
σόΠεڐՄऔಘ let cameraStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) switch (cameraStatus) { case
.authorized: // ༻Մೳ case .restricted, .notDetermined: // ༻ڐՄ AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: {(granted: Bool) in // OK or CancelͰgrantedͷBool͕มΘΔ }) break case .denied: // ༻ෆՄ break }
3. ϋϚͬͨ͜ͱฤ
ϋϚͬͨ͜ͱ A. localMediaStream͕औΕͳ͍ B. remoteMediaStream͕өΒͳ͍ C. ϑϨʔϜϨʔτ͕มߋͰ͖ͳ͍
A. localMediaStream͕औΕͳ͍
localStream͕औΕͳ͍ // peerΠχγϟϥΠζ SKWNavigator.initialize(peer) // constraintsઃఆ let constraints:SKWMediaConstraints = SKWMediaConstraints.init()
// ΧϝϥϞʔυઃఆ constraints.cameraMode = .CAMERA_MODE_ADJUSTABLE // ΧϝϥͷҐஔઃఆ constraints.cameraPosition = .CAMERA_POSITION_FRONT // localMediaStreamऔಘ localMediaStream = SKWNavigator.getUserMedia(constraints) 4USFBNܗࣜͰऔಘͰ͖Δ͚Ͳ ࣗͷө૾͕දࣔ͞Εͳ͔ͬͨ ॳ͜ͷ෦ͷهड़͕ൈ͚͍ͯͨ
localStream͕औΕͳ͍ // peerΠχγϟϥΠζ SKWNavigator.initialize(peer) // constraintsઃఆ let constraints:SKWMediaConstraints = SKWMediaConstraints.init()
// ΧϝϥϞʔυઃఆ constraints.cameraMode = .CAMERA_MODE_ADJUSTABLE // ΧϝϥͷҐஔઃఆ constraints.cameraPosition = .CAMERA_POSITION_FRONT // localMediaStreamऔಘ localMediaStream = SKWNavigator.getUserMedia(constraints) ಛʹฦΓͳ͍͕ؔͩ هࡌ͠ͳ͍ͱ͋Γ
B. remoteMediaStream͕өΒͳ͍
remoteMediaStream͕өΒͳ͍ // MediaConnectionͷCALLBACKΛઃఆ mediaConnection.on(SKWMediaConnectionEventEnum.MEDIACONNECTION_EVENT _STREAM, callback: {(obj) -> Void in
self.remoteMediaStream = obj as? SKWMediaStream DispatchQueue.global(qos: .default).async { let remoteVideo:SKWVideo = self.view.viewWithTag(1002) as! SKWVideo remoteVideo.isUserInteractionEnabled = true remoteVideo.addSrc(self.remoteMediaStream, track: 0) } }) ૬ख͔ΒૹΒΕ͍ͯΔͣͷө ૾͕өΒͳ͔ͬͨ
remoteMediaStream͕өΒͳ͍ // MediaConnectionͷCALLBACKΛઃఆ mediaConnection.on(SKWMediaConnectionEventEnum.MEDIACONNECTION_EVENT _STREAM, callback: {(obj) -> Void in
self.remoteMediaStream = obj as? SKWMediaStream DispatchQueue.global(qos: .default).async { let remoteVideo:SKWVideo = self.view.viewWithTag(1002) as! SKWVideo remoteVideo.isUserInteractionEnabled = true remoteVideo.addSrc(self.remoteMediaStream, track: 0) } }) ඳըॲཧ͕ඞཁʹͳΔͷͰ NBJO2VFVFͰઃఆ͢Δඞཁ͕͋ͬͨ
C. ϑϨʔϜϨʔτ͕มߋͰ͖ͳ͍
ܦҢ • ϏσΦ௨Λߦ͏ʹɺܭࢉ্ԼهͷଳҬ͕ ඞཁʢ1ΫϥΠΞϯτʣ Իɿ500Kbps ө૾ɿ2Mbps • ʢಛʹʣֶߍͩͱڞ༗ωοτϫʔΫͷͨΊɺ 1ΫϥεͰडߨ͢ΔͱԆ͕ଟ͘ൃੜͨ͠
ʮ༻ଳҬΛݮΒͤͳ͍ʁʯ
ௐࠪ͢Δ SkyWayͷυΩϡϝϯτʹ هࡌͳ͠ɾɾɾ
͔͠͠ʂ
SKMediaConstraintsͷ ϓϩύςΟʹ maxFrameRate͕ ͋Γ·ͨ͠ʂ
͑·ͤΜͰͨ͠
ެࣜͰඇରԠͱճ͞Ε͍ͯ·ͨ͠ https://support.skyway.io/hc/ja/community/posts/115000352647-ϑϨʔϜϨʔτͷมߋ͕ө͞Ε·ͤΜ
ϝδϟʔόʔδϣϯͰ ରԠ͞ΕΔ͜ͱΛ ظ͍ͨ͠Ͱ͢ʂ
·ͱΊ
·ͱΊ • iOSͰϏσΦ௨ΞϓϦҙ֎ͱ؆୯ʹ࡞ΕΔ • ҙ֎ͱ͋ͬ͞Γ৹ࠪ௨Δ • ϒϥβ <-> ΞϓϦؒ༻Մೳ •
WebRTCଟछଟ༷ͳ༻్͕͋Δʂ
Weblioӳձ WebΞϓϦ ·ͩ·ͩWebRTCʹ ྗΛೖΕ͍͖ͯ·͢ʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠