├── LICENSE ├── README.md ├── function.js ├── index.html └── package.json /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Michael McDonald 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flaming Specs 2 | Flaming Specs combines [Firebase Storage](https://firebase.google.com/storage) 3 | with the [Google Cloud Vision API](https://cloud.google.com/vision) through 4 | [Google Cloud Functions](https://cloud.google.com/functions), all in ~100 LoC! 5 | 6 | This is a demo for a presentation given at 7 | [Serverless Conf](http://serverlessconf.io/) on May 27th, 2016 8 | by [Frank van Puffelen](https://github.com/puf) and myself. Slides are available 9 | here. 10 | 11 | You can view the public demo [here](http://fir-cloudvisiontest.firebaseapp.com). 12 | 13 | # Setup 14 | 15 | ## Create a Firebase Account 16 | 17 | Create an account through the [Firebase Console](https://console.firebase.com), 18 | and upgrade to Blaze plan. This will allow you to access Cloud resources, 19 | like Cloud Functions and the Cloud Vision API. 20 | 21 | ## Modify the code 22 | 23 | There are two `TODO:`s where you must add your app keys into JSON configuration, 24 | one in `index.html` and one in `function.js`. This information comes from the 25 | [Firebase Console](https://console.firebase.com) for your prroject. 26 | 27 | ## Host the website 28 | 29 | Install the Firebase CLI: `npm install -g firebase-tools`, run `firebase init`, 30 | and move `index.html` into your app's public folder. From there, you can either 31 | run `firebase serve` to locally test your app, or `firebase deploy` to host 32 | your app on the public internet. 33 | 34 | ## Deploy your function 35 | 36 | [Sign up for the GCF Alpha](https://docs.google.com/a/google.com/forms/d/1WQNWPK3xdLnw4oXPT_AIVR9-gd6DLo5ZIucyxzSQ5fQ/viewform), and when accepted, follow the instructions to 37 | deploy a function (either via the console or via the CLI). The function called 38 | will be named `visiondetect`, since that's what's exported from `function.js`. 39 | 40 | # Contact 41 | Reach out to me [@asciimike](https://www.twitter.com/asciimike) or 42 | [mcdonald@firebase.com](mailto:mcdonald@firebase.com) to let me know what you 43 | think! 44 | -------------------------------------------------------------------------------- /function.js: -------------------------------------------------------------------------------- 1 | // Pull in Firebase and GCloud deps 2 | var firebase = require('firebase'); 3 | var gcloud = require('gcloud')({ 4 | projectId: process.env.GCP_PROJECT, 5 | }); 6 | 7 | // Initialize Firebase App with service account 8 | // TODO: get values from https://firebase.google.com/docs/server/setup#initialize_the_sdk 9 | firebase.initializeApp({ 10 | serviceAccount: { 11 | "project_id": "", 12 | "private_key": "", 13 | "client_email": "" 14 | }, 15 | databaseURL: "" 16 | }); 17 | 18 | // Get GCS, Cloud Vision API 19 | var gcs = gcloud.storage(), 20 | vision = gcloud.vision(); 21 | 22 | function visiondetect(context, data) { 23 | if (data !== undefined) { 24 | // Create Firebase Storage public URL 25 | var urlString = "https://firebasestorage.googleapis.com/v0/b/" + data.bucket + "/o/" + data.name.replace(/\//, '%2F') + "?alt=media&token=" + data.metadata.firebaseStorageDownloadTokens; 26 | 27 | // Create GCS File from the data 28 | var file = gcs.bucket(data.bucket).file(data.name); 29 | 30 | // Use GCS File in the Cloud Vision API 31 | vision.detectLabels(file, { 32 | verbose: true 33 | }, function(err, labels, apiResponse) { 34 | if (err) { 35 | context.failure("Vision detection failed") 36 | } else { 37 | var ref = firebase.database().ref("images"); 38 | ref.push({ 39 | "url": urlString, 40 | "name": data.name, 41 | "labels": labels 42 | }, function(error) { 43 | if (error) { 44 | context.failure("Firebase write failed") 45 | } else { 46 | context.success(labels, apiResponse); 47 | } 48 | }); 49 | } 50 | }); 51 | } else { 52 | context.failure('No data payload defined!'); 53 | } 54 | } 55 | 56 | module.exports = { 57 | visiondetect: visiondetect 58 | }; 59 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Firebase + Cloud Vision Stream 5 | 6 | 65 | 66 | 67 |
    68 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name": "firebase-cloud-vision-test", 2 | "description": "testing firebase storage + cloud functions + cloud vision", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "firebase": "3.0.3", 6 | "gcloud": "0.34.0" 7 | } 8 | } 9 | --------------------------------------------------------------------------------