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
taminif
April 22, 2017
Programming
3
530
ビデオ通話アプリのお話
Skywayサービスを利用して、iOSでWebRTCを実装した話です。
taminif
April 22, 2017
Tweet
Share
More Decks by taminif
See All by taminif
「とりあえずAI」が招く悲劇〜私がAIで生産性を下げるまでの話〜 / The tragedy caused by "AI for now" - The story of how I used AI to reduce my productivity
taminif
1
200
PuppeteerとPlaywrightの15日間の演劇 / relation of Puppeteer and Playwright
taminif
3
2.2k
Redashの開発はじめました / How to get started Redash development
taminif
0
760
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
500
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
5.8k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.6k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
1k
オンライン英会話とSkyWay
taminif
0
520
オンライン英会話アプリとSkyWay
taminif
0
460
Other Decks in Programming
See All in Programming
print("Hello, World")
eddie
2
530
請來的 AI Agent 同事們在寫程式時,怎麼用 pytest 去除各種幻想與盲點
keitheis
0
120
testingを眺める
matumoto
1
140
複雑なドメインに挑む.pdf
yukisakai1225
5
1.2k
Kiroで始めるAI-DLC
kaonash
2
590
Namespace and Its Future
tagomoris
6
700
Laravel Boost 超入門
fire_arlo
3
210
Design Foundational Data Engineering Observability
sucitw
3
200
Deep Dive into Kotlin Flow
jmatsu
1
340
ユーザーも開発者も悩ませない TV アプリ開発 ~Compose の内部実装から学ぶフォーカス制御~
taked137
0
170
「手軽で便利」に潜む罠。 Popover API を WCAG 2.2の視点で安全に使うには
taitotnk
0
860
Swift Updates - Learn Languages 2025
koher
2
470
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
70
11k
Into the Great Unknown - MozCon
thekraken
40
2k
Become a Pro
speakerdeck
PRO
29
5.5k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Automating Front-end Workflow
addyosmani
1370
200k
Making the Leap to Tech Lead
cromwellryan
135
9.5k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3.1k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
840
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
Designing for humans not robots
tammielis
253
25k
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ʹ ྗΛೖΕ͍͖ͯ·͢ʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠