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
560
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
270
「とりあえず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
820
私の生活を変えた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
560
Other Decks in Programming
See All in Programming
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
140
不幸な GC
chencmd
0
890
Oxlintはいいぞ(続)
yug1224
1
560
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
180
AIに既存システムを理解させる技術 ~レガシーを見捨てないハーネスエンジニアリング入門~
ochtum
0
210
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
160
RSSとCodexを使ってX投稿自動化してみた
ochtum
0
110
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
55
36k
Building an Out-of-Order CPU
latte72
1
720
PyConJP2026_wat_Python × Signal Processing: How to Draw Pictures with Sound Using Spectrogram Art
wat
0
680
Foundry Localでエージェント開発
seosoft
0
150
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
0
400
Featured
See All Featured
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
680
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
430
Code Review Best Practice
trishagee
74
20k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.3k
Documentation Writing (for coders)
carmenintech
77
5.5k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
490
Building an army of robots
kneath
306
46k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
HDC tutorial
michielstock
2
850
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Leo the Paperboy
mayatellez
8
2.2k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
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ʹ ྗΛೖΕ͍͖ͯ·͢ʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠