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
550
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ビデオ通話アプリのお話
Skywayサービスを利用して、iOSでWebRTCを実装した話です。
taminif
April 22, 2017
More Decks by taminif
See All by taminif
React Native New Architecture 移行実践報告
taminif
1
260
「とりあえずAI」が招く悲劇〜私がAIで生産性を下げるまでの話〜 / The tragedy caused by "AI for now" - The story of how I used AI to reduce my productivity
taminif
1
330
PuppeteerとPlaywrightの15日間の演劇 / relation of Puppeteer and Playwright
taminif
3
2.3k
Redashの開発はじめました / How to get started Redash development
taminif
0
810
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
550
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
6.3k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.7k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
1k
オンライン英会話とSkyWay
taminif
0
550
Other Decks in Programming
See All in Programming
Cloudflare is Agents
chimame
0
180
How I Won Prize Money at a Hackathon Using Codex and Symphony Alpha
yasei_no_otoko
0
120
生成AIで帳票OCRが「簡単に」作れる時代になった?
kon_shou
0
1.2k
React本体のコードリーディング
high_g_engineer
1
160
AIに既存システムを理解させる技術 ~レガシーを見捨てないハーネスエンジニアリング入門~
ochtum
0
150
異なる設計思想のフレームワークを経験して得た学び
amekuhideki
1
540
承認済みなのに差戻しできてしまうバグ、型で潰せます
shinchit
0
110
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
380
プロポーザルを書いてもらう
pvcresin
0
580
Introducing Stack Pull Request in GitHub
kkamegawa
0
100
不幸な GC
chencmd
0
740
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
190
Featured
See All Featured
The Limits of Empathy - UXLibs8
cassininazir
1
610
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
240
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
250
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.8k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
390
Building an army of robots
kneath
306
46k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
180
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
280
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ʹ ྗΛೖΕ͍͖ͯ·͢ʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠