SlideShare ist ein Scribd-Unternehmen logo
1 von 67
Downloaden Sie, um offline zu lesen
ADAPTIVE MEDIA PLAYER
BASED ON HTML5
陳建⾠ jessechen
yapi.js
surf, sb, football, draft beer, kktv
jessechen陳建⾠
http://blog.hellojcc.tw
OTTVOD SERVICE
台⽇韓中
超⼤⽚庫
⼤數據精準推薦
離線播放
投放⾄電視
PLAYBACK EXPERIENCE
ON WEB
WITH HTML5
影⽚
yapi .js
(台)
WHAT IS BEING PLAYED
media
analog-to-
digital adapter
digital raw data
PREPARE MEDIA
1. Make it digital
analog signal
H.264 / H.265
Encode
PREPARE MEDIA
2. Encode video file
Raw data .mp4 / .ts file
Easier for storage and transference
server holds
media
VINTAGE WAY
Player get it and
play
single file
super slow
server holds
media
EFFICIENT WAY
Player get part
of video and
start play
streaming
(progressive download)
Keep requesting
rest part of
video during
playback
inflexible
PREPARE MEDIA
3. Fit adaptive need
.mp4 / .ts file
more storage needed but much flexible
different bitrate
+
+
fragments
manifest
file
MANIFESTTELLS
- adaptions: video, audio or subtitle
- available bitrates
- how file is fragmented
- encryption
ADAPTIVE STREAMINGTYPES
SS
Smooth Streaming
HLS
HTTP Live Streaming
DASH

Dynamic Adaptive
Streaming through HTTP
.mp4 / .ts file different bitrate
+
+
fragments
manifest
file
Raw data
imaging there are thousands of media needs to handle
CONTENT OF KKTV IS

PREPARED WITH

MASS
https://github.com/KKBOX/mass
https://goo.gl/6TCmWqintroduction by Jinkuen:
download
adaptive streaming
client
yapi.js
media
manifest
file
adaptive

algorithm
fragments
adaptive algorithm decides
which quality to download
• network status
• how long does buffered duration left
algorithm considering…
adaptive
starting lag
buffering 

times / duration
overall bitrate
a/v sync
decode
decrypt
‘playback’
client
yapi.js
media
manifest
file
fragments
decrypt
encryption + decryption
H.264 / H.265
Encode
ENCRYPTION
Raw data .mp4 / .ts file
encryption
implemented
here
CLIENT SIDE DECRYPTION
• Client get a license instead of a key
• A blackbox/sandbox get the key by processing license
• That blackbox/sandbox provide key for decryption and
directly output to display
• This solution called DRM(Digital Right Management)
DRM ON BROWSER
• For browser, that blackbox called CDM 

(Content Decrypt Module)
• Each browser support different DRM
context - “a blackbox or sandbox get the key by
processing license”
DRM ON BROWSER
Widevine FairplayPlayready Primetime
Widevine
INTRODUCE EME
• Even though browser support its own DRM, 

W3C defines a EME spec, in order to expose same
api to use
• prefixed api was implemented on earlier version of
chrome(smart tv)
Encrypted Media Extension
YAPI’S PROTECTION LOGIC
• implement protection on client side through EME
• give what DRM server needs to retrieve license
• deal with different browsers (versions)
EME
CDM
attempting to
play encrypted
media
get ‘challenge’
DRM
license
server
request with challenge
get license
yapi
provide license
for CDM to
decrypt content
EME
CDM
PROTECTION LOGIC FLOW
a/v sync
decode
html5 media element + MSE
MEDIA ELEMENT
var videoNode = document.createElement(‘video’);
videoNode.src = VIDEO_URL;
With html5 media element, you can play single video source easily
single source multiple source
+
+
MSE
“ MSE (Media Source Extension) extends HTMLMediaElement to allow
JavaScript to generate media streams for playback.
Allowing JavaScript to generate streams facilitates a variety of use cases like
adaptive streaming and time shifting live streams.“
media source extension
var video = document.createElement(‘video’);
video.src = VIDEO_URL
MEDIASOURCE IS A ‘SOURCE’
set ‘src’ attribute of video element to an url pointed to media
source
new window.MediaSource();window.URL.createObjectURL(ms);
SOURCE BUFFER
sourceBufferVideo = ms.addSourceBuffer(VIDEO_CODEC);

sourceBufferAudio = ms.addSourceBuffer(AUDIO_CODEC);
// get stream buffer via network
sourceBufferVideo.appendBuffer(buffer);
// sourcebuffer provides buffer info after append complete
BUFFER INFO
var buffered = sourceBuffer.buffered;

buffered.length; // how many discontinuous buffered time range
buffered.start(0); // first buffer start time

buffered.end(0); // first buffer end time
get buffer information from buffered attribute
MSE EXTENDS MEDIA ELEMENT
• MSE focus on providing stream buffer to media
element
• playback behavior still hold by media element

e.g play, pause, seek
a/v sync
decode
‘playback’
client
yapi.js
media
manifest
file
fragments
decrypt
streaming
adaptive
protection / EME
mediaElement / MSE
client
yapi.js
BETWEEN MODULES
1. hold reference
problems
• dependency
streaming adaptive
BETWEEN MODULES
2. a parent module
problems
• defining ‘parent’
• multiple parent modules?
streaming
adaptive
parent
parent?
BETWEEN MODULES
3. event system
• modules are parallel
• semantic event name
indicates current ‘state’ of
player
streaming
adaptive
protection / EME
mediaElement / MSE
eventBus
streaming
adaptive
MSECtrl
eventBus
eventBus
eventBus
eventBus
function downloadFragment() {}streaming
adaptive
eventBus
eventBus
MSECtrl eventBus
function calculateQuality() {}
function appendToSourceBuffer() {}
function onDownloaded() {

// notify FRAGMENT_DOWNLOADED

}
function onAppended() {

// notify FRAGMENT_APPENDED

}
register
eventBus.mapHandler(‘FRAGMENT_DOWNLOADED’, )adaptive.calculateQuality
eventBus.mapHandler(‘FRAGMENT_DOWNLOADED’, )MSECtrl.appendToSourceBuffer
eventBus.mapHandler(‘FRAGMENT_APPENDED’, )streaming. downloadFragment
{











}
FRAGMENT_DOWNLOADED: [ ,



],
adaptive. calculateQuality
MSECtrl. appendToSourceBuffer
FRAGMENT_APPENDED: [ ]streaming. downloadFragment
eventBus
function downloadNextFragment() {}streaming
adaptive
eventBus
eventBus
MSECtrl eventBus
function calculateQuality() {}
function appendToSourceBuffer() {}
function onDownloaded() {

eventBus.dispatch(‘FRAGMENT_DOWNLOADED’)

}
function onAppended() {

// notify FRAGMENT_APPENDED

}
dispatch event
eventBus
{











}
FRAGMENT_DOWNLOADED: [ ,



],
adaptive. calculateQuality
MSECtrl. appendToSourceBuffer
FRAGMENT_APPENDED: [ ]streaming. downloadFragment
invoke callbacks
function downloadNextFragment() {}streaming
adaptive
eventBus
eventBus
MSECtrl eventBus
function calculateQuality() {}
function appendToSourceBuffer() {}
function onDownloaded() {

eventBus.dispatch(‘FRAGMENT_DOWNLOADED’)

}
function onAppended() {

eventBus.dispatch(‘FRAGMENT_APPENDED’)

}
dispatch event
eventBus
{











}
FRAGMENT_DOWNLOADED: [ ,



],
adaptive. calculateQuality
MSECtrl. appendToSourceBuffer
FRAGMENT_APPENDED: [ ]streaming. downloadFragment
invoke callbacks
works with app level
yapi.js
app
ui
client
api
works with app level
yapi.js
app
ui
client
events
api
MEDIA EVENTS
http://www.w3.org/2010/05/video/mediaevents.html
Dispatched by HTML5 media element, notifying playback process
YAPI PROXY/PATCH EVENTS
Media
Element
event event with same name
yapi.js
USEFUL MEDIA EVENTS
loadstart: Indicate loading media begins, this fires when setting src attribute
loadedmetadata: while element has basic info of playback, e.g duration
timeupdate: while current time of playback is ticking
seeking/seeked: while conducting seek
ended: playback ends
play/playing: playback resume from other status to playing
ADDITIONAL EVENTS
loadedmanifest: after manifest is loaded/parsed
bitratechanged: when bitrate is changed
enableabr: when adaptive activation changed
buffering: when playback pending
cuechanged: webvtt subtitle cue changed (in and out)
yapi.load(MANIFEST_URL); // exposed api
yapi.addEventListener(‘playing’, onPlaying);
function onPlaying() {

// app logic

// or ui reaction, e.g showing playing status ui

}
// onPlaying invoked when playing
app
yapi ui
LESSONS
1. test case helps
2. handle errors
3. boss wants ‘numbers’
streaming
adaptive
protection / EME
mediaElement / MSE
client
yapi.js
statistic
playing smoothly is not
enough
you need to tell how
good it is
LIVE DEMO
https://app.kktv.me
mse spec: https://goo.gl/L3HPKP
media event sample: https://goo.gl/BsrH18

MDN media element: https://goo.gl/JsojcN
HTML MediaElement doc: https://goo.gl/Y3lbO0

dash.js: https://goo.gl/xAm2Ve
THANKYOU
KKTV is hiring

web / android / iOS / backend developers
jessechen@kktv.me

Weitere ähnliche Inhalte

Was ist angesagt?

Plug in development
Plug in developmentPlug in development
Plug in development
Lucky Ali
 
Optimising Productivity with AWS Developer Tools
Optimising Productivity with AWS Developer ToolsOptimising Productivity with AWS Developer Tools
Optimising Productivity with AWS Developer Tools
Amazon Web Services
 

Was ist angesagt? (20)

Exam Overview 70-533 Implementing Azure Infrastructure Solutions
Exam Overview 70-533 Implementing Azure Infrastructure SolutionsExam Overview 70-533 Implementing Azure Infrastructure Solutions
Exam Overview 70-533 Implementing Azure Infrastructure Solutions
 
CIRCUIT 2015 - Monitoring AEM
CIRCUIT 2015 - Monitoring AEMCIRCUIT 2015 - Monitoring AEM
CIRCUIT 2015 - Monitoring AEM
 
Migrating from Pivotal tc Server on-prem to IBM Liberty in the cloud
Migrating from Pivotal tc Server on-prem to IBM Liberty in the cloudMigrating from Pivotal tc Server on-prem to IBM Liberty in the cloud
Migrating from Pivotal tc Server on-prem to IBM Liberty in the cloud
 
AWS Elastic Beanstalk: Running Multi-Container Docker Applications - DevDay L...
AWS Elastic Beanstalk: Running Multi-Container Docker Applications - DevDay L...AWS Elastic Beanstalk: Running Multi-Container Docker Applications - DevDay L...
AWS Elastic Beanstalk: Running Multi-Container Docker Applications - DevDay L...
 
Plug in development
Plug in developmentPlug in development
Plug in development
 
Vmware vSphere Api Best Practices
Vmware vSphere Api Best PracticesVmware vSphere Api Best Practices
Vmware vSphere Api Best Practices
 
Exploring VMware APIs by Preetham Gopalaswamy
Exploring VMware APIs by Preetham GopalaswamyExploring VMware APIs by Preetham Gopalaswamy
Exploring VMware APIs by Preetham Gopalaswamy
 
2014 cf summit_clustering
2014 cf summit_clustering2014 cf summit_clustering
2014 cf summit_clustering
 
Full slidescr16
Full slidescr16Full slidescr16
Full slidescr16
 
Learn you some Ansible for great good!
Learn you some Ansible for great good!Learn you some Ansible for great good!
Learn you some Ansible for great good!
 
Java and windows azure cloud service
Java and windows azure cloud serviceJava and windows azure cloud service
Java and windows azure cloud service
 
Don't touch that server
Don't touch that serverDon't touch that server
Don't touch that server
 
WebSphere App Server vs JBoss vs WebLogic vs Tomcat (InterConnect 2016)
WebSphere App Server vs JBoss vs WebLogic vs Tomcat (InterConnect 2016)WebSphere App Server vs JBoss vs WebLogic vs Tomcat (InterConnect 2016)
WebSphere App Server vs JBoss vs WebLogic vs Tomcat (InterConnect 2016)
 
Google App Engine
Google App EngineGoogle App Engine
Google App Engine
 
Adobe AEM Maintenance - Customer Care Office Hours
Adobe AEM Maintenance - Customer Care Office HoursAdobe AEM Maintenance - Customer Care Office Hours
Adobe AEM Maintenance - Customer Care Office Hours
 
Optimising Productivity with AWS Developer Tools
Optimising Productivity with AWS Developer ToolsOptimising Productivity with AWS Developer Tools
Optimising Productivity with AWS Developer Tools
 
HTML5 Refresher
HTML5 RefresherHTML5 Refresher
HTML5 Refresher
 
Aem offline content
Aem offline contentAem offline content
Aem offline content
 
Google app-engine-cloudcamplagos2011
Google app-engine-cloudcamplagos2011Google app-engine-cloudcamplagos2011
Google app-engine-cloudcamplagos2011
 
ARC304 Solutions in Action - AWS re: Invent 2012
ARC304 Solutions in Action - AWS re: Invent 2012ARC304 Solutions in Action - AWS re: Invent 2012
ARC304 Solutions in Action - AWS re: Invent 2012
 

Ähnlich wie yapi.js introduction (mopcon 2016 version)

HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
Patrick Lauke
 
Building video applications on Windows 8 with Windows Azure Media Services
Building video applications on Windows 8 with Windows Azure Media ServicesBuilding video applications on Windows 8 with Windows Azure Media Services
Building video applications on Windows 8 with Windows Azure Media Services
Mingfei Yan
 
Building video application on windows 8 with Windows Azure Media Services
Building video application on windows 8 with Windows Azure Media ServicesBuilding video application on windows 8 with Windows Azure Media Services
Building video application on windows 8 with Windows Azure Media Services
Mingfei Yan
 
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
Patrick Lauke
 

Ähnlich wie yapi.js introduction (mopcon 2016 version) (20)

audio, video and canvas in HTML5 - standards>next Manchester 29.09.2010
audio, video and canvas in HTML5 - standards>next Manchester 29.09.2010audio, video and canvas in HTML5 - standards>next Manchester 29.09.2010
audio, video and canvas in HTML5 - standards>next Manchester 29.09.2010
 
iOSDC 2018 動画をなめらかに動かす技術
iOSDC 2018 動画をなめらかに動かす技術iOSDC 2018 動画をなめらかに動かす技術
iOSDC 2018 動画をなめらかに動かす技術
 
IIS Smooth Streaming
IIS Smooth StreamingIIS Smooth Streaming
IIS Smooth Streaming
 
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
HTML5 APIs - native multimedia support and beyond - University of Leeds 05.05...
 
HTML5 Multimedia: where we are, where we're going
HTML5 Multimedia: where we are, where we're goingHTML5 Multimedia: where we are, where we're going
HTML5 Multimedia: where we are, where we're going
 
Building video applications on Windows 8 with Windows Azure Media Services
Building video applications on Windows 8 with Windows Azure Media ServicesBuilding video applications on Windows 8 with Windows Azure Media Services
Building video applications on Windows 8 with Windows Azure Media Services
 
Creating Flash Content for Multiple Screens
Creating Flash Content for Multiple ScreensCreating Flash Content for Multiple Screens
Creating Flash Content for Multiple Screens
 
Craft 2019 - “The Upside Down” Of The Web - Video technologies
Craft 2019 - “The Upside Down” Of The Web - Video technologiesCraft 2019 - “The Upside Down” Of The Web - Video technologies
Craft 2019 - “The Upside Down” Of The Web - Video technologies
 
Multimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audioMultimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audio
 
Building video application on windows 8 with Windows Azure Media Services
Building video application on windows 8 with Windows Azure Media ServicesBuilding video application on windows 8 with Windows Azure Media Services
Building video application on windows 8 with Windows Azure Media Services
 
Leveraging BlazeDS, Java, and Flex: Dynamic Data Transfer
Leveraging BlazeDS, Java, and Flex: Dynamic Data TransferLeveraging BlazeDS, Java, and Flex: Dynamic Data Transfer
Leveraging BlazeDS, Java, and Flex: Dynamic Data Transfer
 
Structure your Play application with the cake pattern (and test it)
Structure your Play application with the cake pattern (and test it)Structure your Play application with the cake pattern (and test it)
Structure your Play application with the cake pattern (and test it)
 
Flash for Mobile Devices
Flash for Mobile DevicesFlash for Mobile Devices
Flash for Mobile Devices
 
CLI319 Microsoft Desktop Optimization Pack: Planning the Deployment of Micros...
CLI319 Microsoft Desktop Optimization Pack: Planning the Deployment of Micros...CLI319 Microsoft Desktop Optimization Pack: Planning the Deployment of Micros...
CLI319 Microsoft Desktop Optimization Pack: Planning the Deployment of Micros...
 
Responsive Videos, mehr oder weniger
Responsive Videos, mehr oder wenigerResponsive Videos, mehr oder weniger
Responsive Videos, mehr oder weniger
 
FMS Administration Seminar
FMS Administration SeminarFMS Administration Seminar
FMS Administration Seminar
 
FMS 3.5
FMS 3.5FMS 3.5
FMS 3.5
 
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
HTML5 multimedia - browser-native video and audio - JSDay / Verona / 17 May 2012
 
Web Apps
Web AppsWeb Apps
Web Apps
 
Videostream compression in iOS
Videostream compression in iOSVideostream compression in iOS
Videostream compression in iOS
 

Kürzlich hochgeladen

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 

yapi.js introduction (mopcon 2016 version)