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
720
私の生活を変えたHeadless Chrome / Headless Chrome who changed my life
taminif
3
430
WebSocketをiOSに持ち込んで辛い思いをした経験がありますか!? / have you painful experience in web socket?
taminif
3
5.4k
LINEで馬券を購入する / Purchase a betting ticket at LINE
taminif
1
1.5k
SkyWayで一年間運用してきたけどWebRTCってつらいんじゃないの
taminif
2
960
オンライン英会話とSkyWay
taminif
0
460
オンライン英会話アプリとSkyWay
taminif
0
410
Mac1台でアプリを作る時代再び
taminif
0
410
Other Decks in Programming
See All in Programming
Security_for_introducing_eBPF
kentatada
0
110
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
180
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
250
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
750
Cloudflare MCP ServerでClaude Desktop からWeb APIを構築
kutakutat
1
540
Haze - Real time background blurring
chrisbanes
1
510
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
760
クリエイティブコーディングとRuby学習 / Creative Coding and Learning Ruby
chobishiba
0
3.9k
42 best practices for Symfony, a decade later
tucksaun
1
180
HTTP compression in PHP and Symfony apps
dunglas
2
1.7k
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
220
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
200
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
RailsConf 2023
tenderlove
29
940
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
111
49k
Six Lessons from altMBA
skipperchong
27
3.5k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
32
2.7k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.3k
Designing for humans not robots
tammielis
250
25k
For a Future-Friendly Web
brad_frost
175
9.4k
4 Signs Your Business is Dying
shpigford
181
21k
Facilitating Awesome Meetings
lara
50
6.1k
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ΞϓϦ։ൃΛ͢Δ্Ͱඇৗʹศར •
μϯϩʔυεΫϦʔϯϏϡʔͷղੳͰ ͖ΔͷͰɺͱΓ͋͑ͣೖΕΔͱ͍͏ͷҰߟͷ ༨͋Γ
͋Γ͕ͱ͏͍͟͝·ͨ͠