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
September 16, 2017
Programming
1
1.1k
英会話サービスのために開発したビデオチャットアプリの技術
iOSDC 2017 TrackC 13:30〜のトークです
taminif
September 16, 2017
Tweet
Share
More Decks by taminif
See All by taminif
PuppeteerとPlaywrightの15日間の演劇 / relation of Puppeteer and Playwright
taminif
3
2.1k
Redashの開発はじめました / How to get started Redash development
taminif
0
730
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
450
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
5.5k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.5k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
970
オンライン英会話とSkyWay
taminif
0
480
オンライン英会話アプリとSkyWay
taminif
0
420
Mac1台でアプリを作る時代再び
taminif
0
410
Other Decks in Programming
See All in Programming
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
370
CDK開発におけるコーディング規約の運用
yamanashi_ren01
2
140
WebDriver BiDiとは何なのか
yotahada3
1
140
sappoRo.R #12 初心者セッション
kosugitti
0
260
一休.com のログイン体験を支える技術 〜Web Components x Vue.js 活用事例と最適化について〜
atsumim
0
520
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
740
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
340
Amazon Bedrock Multi Agentsを試してきた
tm2
1
290
Open source software: how to live long and go far
gaelvaroquaux
0
640
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
750
時計仕掛けのCompose
mkeeda
1
300
Amazon Q Developer Proで効率化するAPI開発入門
seike460
PRO
0
110
Featured
See All Featured
Facilitating Awesome Meetings
lara
52
6.2k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
GitHub's CSS Performance
jonrohan
1030
460k
Music & Morning Musume
bryan
46
6.3k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Navigating Team Friction
lara
183
15k
The Cult of Friendly URLs
andyhume
78
6.2k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
630
Scaling GitHub
holman
459
140k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3k
Transcript
ӳձαʔϏεͷͨΊʹ ࡞ͨ͠ϏσΦνϟοτΞϓϦ ͷٕज़ iOSDC JAPAN 2017 day 1 2017/09/16 େౡ
ޫو@sbntaminif
ຊͷλʔήοτ • SkyWay, Firebaseʹ͍ͭͯΓ͍ͨํ • ্هͷӡ༻ͷݟʹ͍ͭͯڵຯͷ͋Δํ • ӳձαʔϏεʹڵຯͷ͋Δํ • ७ਮʹڵຯͷ͋Δํ
ࣗݾհ • ΣϒϦΦגࣜձࣾWEBΤϯδχΞ + ϓϩμΫτ Ϛωʔδϟʔ • ΞϓϦΤϯδχΞ ʢࣗশʣ •
ීஈژͰಇ͍͍ͯ·͢
http://ejje.weblio.jp/content/ios
Weblio ΦϯϥΠϯࣙॻΛఏڙ͢Δ WebαʔϏεΛ ӡӦ͓ͯ͠Γ·͢
࣮ࣙॻҎ֎ʹ ͜ΜͳWebαʔϏεΛͬ ͍ͯ·͢
None
WebRTCͱʢςϯϓϨʣ • W3C͕ఏএ͢ΔP2PϦΞϧλΠϜίϛϡχέʔ γϣϯΛ࣮ݱ͢Δٕज़ • ϓϥάΠϯͳ͠ͰϒϥβؒͷΓͱΓ͕Մೳ • ຊΈΛ؆୯ʹ͚ͩઆ໌͠·͢ɻ
؆୯ʹΈ͚ͩ ᶅ௨৴ʂ 456/563/ ʢதܧʣαʔό γάφϦϯά αʔό ᶃ ᶄ ᶄ ᶃ
WebRTCͱʢςϯϓϨʣ • W3C͕ఏএ͢ΔP2PϦΞϧλΠϜίϛϡχέʔ γϣϯΛ࣮ݱ͢Δٕज़ • ϓϥάΠϯͳ͠ͰϒϥβؒͷΓͱΓ͕Մೳ • ຊΈΛ؆୯ʹ͚ͩઆ໌͠·͢ɻ
ΞϓϦͷ ͡Όͳ͍ͷʁ ϒϥβͷʁ
ΞϓϦΛ࡞ΔܦҢ
iOSͷSafari WebRTCʹରԠ͍ͯ͠·ͤΜ ʢۙରԠ༧ఆʂʣ
iPhoneiPadͰ Weblioӳձ͕͑ͳ͍
มΘͬͯɺ Weblioӳձֶߍ اۀʹఏڙ͍ͯ͠·͢
·ͨɺֶߍͷதʹ iPadΛतۀʹ༻͢Δॴ ૿͖͑ͯ·ͨ͠
ʮWeblioӳձΛiPadͰ ༻Ͱ͖ͳ͍ʁʯ
None
iOS SafariͰແཧ͚ͩͲ ΞϓϦͰ࣮͢ΕͰ͖Δ
ͦ͏ɺΞϓϦΛ࡞Δඞཁ͕ ͋ͬͨͷͰ͢
https://itunes.apple.com/jp/app/weblio๏ਓӳձ/id1215209006?mt=8
ΞϓϦͷհΛ͠·͢ʂ
ͱͯγϯϓϧͳΞϓϦ ᶃϩάΠϯ
ͱͯγϯϓϧͳΞϓϦ ᶄ࣍ճͷϏσΦϨοεϯ࣌֬ೝ
ͱͯγϯϓϧͳΞϓϦ ᶅϨοεϯ
͜ΜͳΞϓϦͰ͢ʂ • ߹ܭSwiftϑΝΠϧ16ϑΝΠϧʂ Controller4ͭʂ • Storyboard1ϑΝΠϧʹऩ·Δ • ͓ͦΒ͘iOSDCͷதͰͬͱখ͍͞Ξ ϓϦͩͱࢥ͍·͢ʂ
ຊ͜ͷΞϓϦΛ ֤ίϯϙʔωϯτʹ͚ͯ հ͢Δ͜ͱͰ
ͦΕͧΕͷ෦ʹ༻͞Εͯ ͍Δٕज़ӡ༻ʹ͍ͭͯͷ ݟΛڞ༗͠·͢
͜ͷࡾͭ ϏσΦ෦ ڭࡐ෦ νϟοτ෦
1. ϏσΦ෦
ઌ΄Ͳհͨ͠௨Γɺ WeblioӳձWebRTCΛ ༻͍ͯ͠·͢
ͪΖΜɺΞϓϦʹ WebRTCͰ࣮͢Δඞཁ͕ ͋Γ·͢
SkyWay: WebRTCΛ؆୯ʹ ࣮ݱ͢ΔαʔϏε https://webrtc.ecl.ntt.com
let options:SKWPeerOption = SKWPeerOption.init() options.key = `APIΩʔ` options.domain = `υϝΠϯ`
peer = SKWPeer.init(options: options) peer?.on(SKWPeerEventEnum.PEER_EVENT_OPEN, callback: {(obj) -> Void in // my peer ID if let ownId = obj as? String { self.videoLessonRtdb.writeSkyWayId(id: ownId) } }) peer?.on(SKWPeerEventEnum.PEER_EVENT_CALL, callback: {(obj) -> Void in let mediaConnection:SKWMediaConnection = obj as! SKWMediaConnection self.videoConnection = mediaConnection mediaConnection.answer(self.localMediaStream) }) ਃ͠༁ఔͷαϯϓϧίʔυ #import <SkyWay/SKWPeer.h> $PDPB1PETͰΠϯετʔϧ ͨ͠ϥΠϒϥϦΛΠϯϙʔτ 1FFSΦϒδΣΫτΛੜ ʢγάφϦϯάαʔόʔʹ ใॻ͖ࠐΈʣ ௨৴։࢝ ͜͜Ͱө૾ͱԻΛૹ৴ ใΛॻ͖ࠐΜͩΒɺ 1FFS*%͕ൃߦ͞Ε·͢
2. νϟοτ෦
Firebase
Firebase • FirebaseGoogle͕ఏڙ͢ΔαʔϏε (Baas?) • iOS, Android, ΣϒͰ༻Մೳ • ։ൃΛॿ͚Δଟ͘ͷػೳ͕͋Γ·͢ɻ
༻͍ͯ͠Δػೳ • AuthͱRealtime Database • AuthೝূػೳΛఏڙͯ͘͠ΕΔαʔϏε • Realtime DatabaseαʔόʔͱΫϥΠΞ ϯτؒͰσʔλΛಉظͯ͠อଘͯ͘͠ΕΔ
αʔϏε
νϟοτͷ࣮ݱ ,FZ7BMVFͰΛอଘ औಘ͢Δࡍ+40/ܗ ࣜͰऔಘͰ͖Δ ҰͭͷϊʔυͰҰͭͷνϟοτΛ ࣮ݱ͍ͯ͠Δ ࣌ܥྻॱʹฒΔ͜ͱͰνϟοτͬΆ͘ දࣔ
Auth let rtdbLoginCompletionHandler: FIRAuthResultCallback = {_,_ in self.setChatObserve() self.setTmObserve() }
let rtdbLoginErrorHandler = { print(‘error’) } FIRAuth.auth()?.signIn(withEmail: `ID`, password: `ύεϫʔυ`, completion: { (user, error) in guard error == nil else { rtdbLoginCompletionHandler() return } rtdbLoginCompletionHandler(user, error) }) ೝূޙͷॲཧΛఆٛ ೝূΤϥʔ࣌ͷॲཧΛఆٛ ೝূॲཧ ͜͜ͰύεϫʔυํࣜͰ ϩάΠϯ
Realtime Database let withBlock = { (snapshot: FIRDataSnapshot) in //
received chat data if let dictionary = snapshot.value as? [String : AnyObject] { guard let isRoleProf = dictionary["is_role_prof"] as? Bool, let timeMsec = dictionary["time_msec"] as? UInt64, let senderIdString = dictionary["sender_id"] as? String, let senderId = Int(senderIdString), let text = dictionary["text"] as? String else { return } let time:Double = Double(timeMsec) / 1000 } var data:ChatDataStruct if isRoleProf { // prof data = ChatDataStruct(messageSender: .YOU, message: text, displayTime: self.displayTimeFormatter.string(from: Date(timeIntervalSince1970: time))) } else { // member data = ChatDataStruct(messageSender: .ME, message: text, displayTime: self.displayTimeFormatter.string(from: Date(timeIntervalSince1970: time))) } self.chatTableReload(data: data) } firebaseChatObserveHandle = firebaseUserReference.child(`Firebaseͷύε `).observe(.childAdded, with: withBlock) 'JSFCBTF͔Βϊʔ υΛड͚औͬͨ࣌ ͷॲཧΛఆٛ ՃࣜͰ0CTFSWFS ηοτ
3. ڭࡐ෦
ڭࡐ෦ • ڭࡐʹը૾Λ༻ʢWebͷ༷ʣ • αʔόʔʹஔ͍ͯ͋ΔڭࡐΛɺ WKWebViewΛ༻ͯ͠ಡΈࠐΈ • ڭࡐͷURLͷΓͱΓʹRealtime DatabaseΛ༻
࣮͜Μͳͱ͜ʹ ͍ͬͯΔFirebase • ڭࡐURLͷૹ৴ • PeerIDͷަ • ϨοεϯதͷϏσΦঢ়گͷࢹ • ڭࡐ্ʹදࣔ͢ΔϚεಉظ
ӡ༻͖ͯͨ͠ݟ
1. SkyWay
ແྉͰ αʔϏεӡ༻Ͱ͖ͦ͏ʁ
͋Γ·ͤΜ • ֶߍͷतۀͰ༻͢ΔͷͰɺ20ਓʙ40ਓ ͘Β͍ͷੜె͕ಉ࣌ʹडߨ • ௨৴ཱ͕֬͢Εϥά1ඵ͔͔Γ·ͤ Μ • ͨͩ͠ωοτϫʔΫ͕උ͞Ε͍ͯΔલఏ
ωοτϫʔΫͲΕ͚ͩ ඞཁͳͷʁ
ඞཁͳଳҬ • 1ΫϥΠΞϯτ͋ͨΓ͜Ε͘Β͍ඞཁ Իɿ500Kbps ө૾ɿ2Mbps • ֶߍͩͱશһ͕ಉ࣌ʹतۀΛ͢ΔͨΊɺ 1ΫϥεͰडߨ͢Δͱଓෆྑ͕ଟ͘ൃੜͨ͠
༻ଳҬΛݮΒͤͳ͍͔ʁ
ϦϦʔε࣌Ͱ͖ͳ͔ͬ ͨͷͰ͕͢ɺਖ਼ࣜ൛ͰͰ ͖ΔΑ͏ʹͳ͍ͬͯ·͢
2. Firebase
ຖ݄ͷྉۚͲ͏ͳͷʁ
ྉۚϓϥϯࡾछྨ͋Γ·͢
4QBSLϓϥϯ ʢແྉʣ 'MBNFϓϥϯ ʢఆֹ՝ۚʣ #MB[Fϓϥϯ ʢैྔ՝ۚʣ ಉ࣌ଓ ্ݶ͋Γ ্ݶͳ͠ ্ݶͳ͠
μϯϩʔυ (#·Ͱ (#·Ͱ (# ετϨʔδ ݄(#·Ͱ ݄(#·Ͱ (# ࣗಈόοΫΞοϓ ͳ͠ ͳ͠ ͋Γ ※2017/09/11ݱࡏ https://firebase.google.com/pricing/
ྫɿ8݄ͷ༻ྔ • ࠷େಉ࣌ଓ250 • μϯϩʔυྔ1.4GB • ετϨʔδ༻ྔ16GBʢαʔϏε։࢝࣌ ͔Βͷ߹ܭʣ ͯ͞ɺ͜ΕͰ͍͘Βʁ
Realtime Databaseͷ ϊʔυཧ
ཧը໘ͰΒ͔͢ தུ
ϊʔυ͕1000Λ͑Δͱ ཧը໘ػೳ͠ͳ͘ͳΔ
͋Δఔੵ͞ΕΔલʹ ׂ͢ΔΑ͏ͳઃܭʹ͠·͠ΐ͏ ʢྫɿʁʣ
Firebaseͷোใ
ظ͚ؒͩͲ ͪΐ͍ͪΐ͍ଓෆྑʹͳΓ·͢
ேํ͕ଟ͍ͷͰ ʹͳΓʹ͍͘Ͱ͕͢ ͜Ε͔Β҆ఆ͢Δ͜ͱΛ ظ͓ͯ͠Γ·͢
·ͱΊ
·ͱΊ • SkyWay, FirebaseڞʹɺॳಈແྉͰ༻Մೳ • ؆୯ͳͷΛ࡞Γ͍ͨͱ͖ɺؾܰʹͬͯΈΔ ͷҰͭ • ಛʹFirebaseΞϓϦ։ൃΛ͢Δ্Ͱඇৗʹศར •
μϯϩʔυεΫϦʔϯϏϡʔͷղੳͰ ͖ΔͷͰɺͱΓ͋͑ͣೖΕΔͱ͍͏ͷҰߟͷ ༨͋Γ
͋Γ͕ͱ͏͍͟͝·ͨ͠