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
React Native New Architecture 移行実践報告
taminif
1
170
「とりあえずAI」が招く悲劇〜私がAIで生産性を下げるまでの話〜 / The tragedy caused by "AI for now" - The story of how I used AI to reduce my productivity
taminif
1
260
PuppeteerとPlaywrightの15日間の演劇 / relation of Puppeteer and Playwright
taminif
3
2.3k
Redashの開発はじめました / How to get started Redash development
taminif
0
780
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
520
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
6k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.6k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
1k
オンライン英会話とSkyWay
taminif
0
530
Other Decks in Programming
See All in Programming
GISエンジニアから見たLINKSデータ
nokonoko1203
0
190
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.5k
Developing static sites with Ruby
okuramasafumi
0
330
開発に寄りそう自動テストの実現
goyoki
2
1.5k
Navigating Dependency Injection with Metro
l2hyunwoo
1
200
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
7
2.4k
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
120
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
140
TerraformとStrands AgentsでAmazon Bedrock AgentCoreのSSO認証付きエージェントを量産しよう!
neruneruo
4
2k
はじめてのカスタムエージェント【GitHub Copilot Agent Mode編】
satoshi256kbyte
0
110
実は歴史的なアップデートだと思う AWS Interconnect - multicloud
maroon1st
0
270
AIの誤りが許されない業務システムにおいて“信頼されるAI” を目指す / building-trusted-ai-systems
yuya4
6
4k
Featured
See All Featured
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
0
23
30 Presentation Tips
portentint
PRO
1
180
Into the Great Unknown - MozCon
thekraken
40
2.2k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.1k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.1k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
0
200
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
0
79
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.7k
The Curse of the Amulet
leimatthew05
0
5.8k
Statistics for Hackers
jakevdp
799
230k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
200
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ʹ ྗΛೖΕ͍͖ͯ·͢ʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠