Google Cloud speech with React Native - reactjs

I am trying to use Google Cloud Speech API so I can pass audio file and receive the translated text but I am stuck to the integration. I already have api key and everything needed but can't find how to use it from react native. In the documentation there is only explanation for node.js (from javascript part). Also there are several libraries out dated or supporting only the one OS. Someone succeeded in that?
The node.js example from the documentation:
// Imports the Google Cloud client library
const Speech = require('#google-cloud/speech');
// Your Google Cloud Platform project ID
const projectId = 'YOUR_PROJECT_ID';
// Instantiates a client
const speechClient = Speech({
projectId: projectId
});
// The name of the audio file to transcribe
const fileName = './resources/audio.raw';
// The audio file's encoding and sample rate
const options = {
encoding: 'LINEAR16',
sampleRate: 16000
};
// Detects speech in the audio file
speechClient.recognize(fileName, options)
.then((results) => {
const transcription = results[0];
console.log(`Transcription: ${transcription}`);
});

You could deploy the code using google app engine and make a post req from react-native.
Also need to configure and use google cloud storage to store the audio file for conversion.
Here is my server code.
const format = require('util').format;
const fs = require('fs');
const express = require('express');
const multer = require('multer');
const requestHttp = require('request');
const {Storage} = require('#google-cloud/storage');
// Instantiate a storage client
const storage = new Storage();
// const upload = multer();
const app = express();
// Imports the Google Cloud client library
const speech = require('#google-cloud/speech');
// Creates a client
const client = new speech.SpeechClient();
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
const encoding = 'LINEAR16';
const sampleRateHertz = 16000;
const languageCode = 'en-US';
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024, // no larger than 5mb, you can change as needed.
},
});
const bucket = storage.bucket(process.env.GCLOUD_STORAGE_BUCKET);
app.post('/upload', upload.single('file') , async (req, res) => {
const file = await req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
// Create a new blob in the bucket and upload the file data.
const blob = bucket.file(req.file.originalname);
const blobStream = blob.createWriteStream({
resumable: false,
});
blobStream.on('error', err => {
next(err);
});
blobStream.on('finish', async () => {
// The public URL can be used to directly access the file via HTTP.
const publicUrl = await format(
`https://storage.googleapis.com/${bucket.name}/${blob.name}`
);
const request = {
config: {
encoding: encoding,
sampleRateHertz: sampleRateHertz,
languageCode: languageCode,
},
audio: {
uri: 'gs://YOUR-Bucket-Name/File-name.ext'
}
};
// Stream the audio to the Google Cloud Speech API
const [response] = await client.recognize(request);
const transcription = response.results
.map(result => result.alternatives[0].transcript)
.join('\n');
console.log(`Transcription: `, transcription);
res.status(200)
.send({
success: 'true',
message: 'Text retrieved successfully',
text: transcription
})
.end();
});
blobStream.end(req.file.buffer);
});
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
console.log('Press Ctrl+C to quit.');
});

deploy this server to Heroku then from your react native app send the post or get request to this server and get the result on your app.
To send post or get request use Axios library https://github.com/axios/axios

Related

Data not uploading to IPFS ( Error uploading file: HTTPError: project id required)

I am working on a NFT marketplace and today, I found out that I can't upload data to the IPFS using http-client. Yesterday, the data was uploading perfectly fine but now it does not upload to the IPFS and existing IPFS URLs also does not return any JSON data. Instead it returns
Public Gateway Is Not Supported Anymore - Setup a Dedicated Gateway
These are the functions that I am using to upload data to IPFS :
const [fileUrl, setFileUrl] = useState(null);
const [formInput, updateFormInput] = useState({
price: "",
name: "",
description: "",
});
async function onChange(e) {
const file = e.target.files[0];
try {
const added = await client.add(file, {
progress: (prog) => console.log(`received: ${prog}`),
});
const url = `https://ipfs.infura.io/ipfs/${added.path}`;
setFileUrl(url);
console.log(fileUrl);
} catch (error) {
console.log("Error uploading file: ", error);
}
}
async function uploadToIPFS() {
const { name, description, price } = formInput;
if (!name || !description || !price || !fileUrl) return;
/* first, upload to IPFS */
const data = JSON.stringify({
name,
description,
image: fileUrl,
});
try {
const added = await client.add(data);
const url = `https://ipfs.infura.io/ipfs/${added.path}`;
/* after file is uploaded to IPFS, return the URL to use it in the transaction */
console.log(url);
return url;
} catch (error) {
console.log("Error uploading file: ", error);
}
}
I am facing the same issue, i think Infura require us create new IPFS project and have to implements projectId and projectSecret to our code
import { create } from 'ipfs-http-client'
const projectId = process.env.NEXT_PUBLIC_INFURA_IPFS_PROJECT_ID
const projectSecret = process.env.NEXT_PUBLIC_INFURA_IPFS_PROJECT_SECRET
const projectIdAndSecret = `${projectId}:${projectSecret}`
const client = create({
host: 'ipfs.infura.io',
port: 5001,
protocol: 'https',
headers: {
authorization: `Basic ${Buffer.from(projectIdAndSecret).toString(
'base64'
)}`,
},
})
IPFS infura has deprecated the public gateways, i.e. it is not available after 10th August, 2022. You can use dedicated gateway by the following steps-
Login to IPFS infura.
Select ipfs from the top left corner where all products is written.
Create an ipfs project. This will require your card details, but you will not be charged upto a quota that is provided in the stats).
After creating the project, click on manage key and select enable dedicated server.
Click here to view

Google Spreadsheet Api not working on mobile devices

I'm using Google Spreadsheets as a lightweight database for my React App. The app is a wedding website and the idea is for users to be able to RSVP and the response gets saved in a Google Spreadsheet. See GitHub for a visual representation of what I mean: https://github.com/michelleroos/mimirgettingmarried
It's working as intended on desktop, meaning RSVP responses get saved to the sheet, but not on mobile and I can't figure out why.
Would love your input! If I could even just understand where to start looking that would be great but there is not a lot of information out there on Google Spreadsheet Api.
const express = require("express");
const app = express();
const { google } = require('googleapis');
const PORT = process.env.PORT || 3001; // use live port or the declared one
var cors = require('cors');
app.use(cors())
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const auth = new google.auth.GoogleAuth({
keyFile: "./config/credentials.json",
scopes: 'https://www.googleapis.com/auth/spreadsheets',
});
const spreadsheetId = "1-R0vjBCOD5hcipk9AQbVUwQAH_0dFvQB2qs5gxsxWg0";
const range = "rsvp";
// api endpoint returns a CB. We decide what to do w res thru CB
app.get("/api/rsvp", async (req, res) => {
// create client instance for auth
const client = await auth.getClient();
// create Google sheets API instance
const googleSheets = google.sheets({ version: "v4", auth: client })
// read rows
const getRows = await googleSheets.spreadsheets.values.get({
auth,
spreadsheetId,
range,
});
// express/app sends to the client (the body)
res.send(getRows.data.values);
});
app.post("/api/rsvp", async (req, res) => {
// create client instance for auth
const client = await auth.getClient();
// create Google sheets API instance
const googleSheets = google.sheets({ version: "v4", auth: client })
const writeRows = await googleSheets.spreadsheets.values.append({
auth,
spreadsheetId,
range,
valueInputOption: "USER_ENTERED", // parses info
resource: {
values: [
// Object.keys(req.body), // header
Object.values(req.body) // values
]
}
})
res.send(writeRows);
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});

Downloading Files from Firebase Storage

I have a function that when clicked downloads a file from firebase storage. I have implemented the function as in the firebase documentation v8. I have also applied the cors policy to allow downloads but the problem is that file is still not being downloaded and I am not getting an error.
Kindly help on this.
Below is my download function.
const handleDownloadFile = async file => {
try {
const url = file.downloadURL;
console.log(file);
const xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = event => {
const blob = xhr.response;
};
xhr.open('GET', url);
xhr.send();
} catch (error) {
console.log(error.message);
}
};
The function accepts the details of the file. Below is a sample object that
{
name: 'Ndov network LOGO - 400.png',
downloadURL: 'https://firebasestorage.googleapis.com/v0/b/tkiā€¦=media&token=2680cc-4043-4676-992a-7e64fe8342f2',
uuid: '1b1c0a4b-80a5-42d4-a698-719a26e3f281'
}
kindly help me understand why I am not getting any errors and the still download, not working.
Easiest way to download file on url that comes from API is to
window.open(url,'_blank');
or you can use some library for downloading files in blob format like
https://www.npmjs.com/package/file-saver
This will open a window and ask the user where they want to save the file locally.
import { getStorage, ref, uploadBytes, getBlob } from 'firebase/storage'
export const downloadFile = (refToFile) => {
const storage = getStorage()
const fileRef = ref(storage, refToFile)
const blob = await getBlob(fileRef)
const blobUrl = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = blobUrl
link.download = 'myfilename.pdf'
link.click()
}

I keep getting an error when using the clarifai 'Demographics" model

TypeError: Cannot read property 'language' of undefined
The demographics model was working few months ago when I used it as 'Clarifai.DEMOGRAPHICS_MODEL' but now it gives a 404 error for the same. I think now I am supposed to use it as 'Clarifai.Demographics' but it gives the error shown in picture.
Am I doing something wrong or is it some Clarifai issue? I am relatively new to react programming and just noticed the app that I had made before using 'Clarifai.DEMOGRAPHICS_MODEL' started showing errors suddenly.
For now, I am just trying to make this work
const onSubmit = () => {
app.models.predict(Clarifai.Demographics, "https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/06/06/15/Chris-Pratt.jpg")
.then(res => console.log(res))
}
NEW EDIT :
Finally, now I can retrieve data from clarifai and send it to frontend. Keeping the backend code here for reference if anyone needs.
--------server.js---------
const express = require('express')
const cors = require('cors')
const posts = require('./demographics.js')
const app = express()
app.use(cors())
app.use(express.json())
const PORT = process.env.PORT || 5000
app.post('/data', posts.demographics)
app.listen(PORT, ()=> {
console.log('Working at port ',PORT)
})
--------demographics.js---------
const {ClarifaiStub, grpc} = require("clarifai-nodejs-grpc");
const stringify = require('json-stringify-safe');
const demographics = (req,res) => {
const stub = ClarifaiStub.grpc()
const metadata = new grpc.Metadata();
metadata.set("authorization", "Key {My_Key}");
stub.PostWorkflowResults(
{
workflow_id: "Demographics",
inputs: [
{data: {image: {url: req.body.input}}}
]
},
metadata,
(err, response) => {
if(response){
const data = stringify(response.results[0].outputs[4].data.regions, null, 2)
res.send(data)
}
else {
console.log(err)
res.status(400)
}
}
)
}
You have to call the request either from the front end or from the backend.
And the demographics now only support requests from the backend.
const {ClarifaiStub} = require("clarifai-nodejs-grpc");
const grpc = require("#grpc/grpc-js");
const metadata = new grpc.Metadata();
metadata.set("authorization", "{My key}");
const stub = ClarifaiStub.json()
stub.PostWorkflowResults(
{
workflow_id: "Demographics",
inputs: [
{data: {image: {url: "https://static.independent.co.uk/s3fs-public/thumbnails/image/2015/06/06/15/Chris-Pratt.jpg"}}}
]
},
metadata,
(err, response) => {
if(response){
console.log(response.results[0].outputs[2].data.regions[0].data.concepts
)
}else {
console.log(err)
}
use this for returning results
// response.results[0].outputs[2].data.regions[0].data.concepts, muliticulture,
// response.results[0].outputs[3].data.regions[0].data.concepts, gender,
//response.results[0].outputs[4].data.regions[0].data.concepts, age,
The Clarifai JS Rest client is now depreciated, the model IDs are not updated and this specific Demographics model is also on the course of depreciation. You can replace it with the new gRPC NodeJS API: https://docs.clarifai.com/api-guide/api-overview/api-clients
You can then get a demographics prediction by calling the new Demographics workflow: https://docs.clarifai.com/api-guide/workflows/workflow-predict (replace 'YOUR_WORKFLOW_ID' by 'Demographics')

Issue connecting to token server with Firebase hosting

I am trying to deploy the Twilio video app to Firebase hosting. Everything works great, except when I try to connect to video conference it tells me the Twilio tokens are invalid.
I found that I need to set up google cloud functions to resolve this. How do you go about converting a server.js file to a cloud function?
Here is my code server.js code:
const express = require('express');
const app = express();
const path = require('path');
const AccessToken = require('twilio').jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;
require('dotenv').config();
const MAX_ALLOWED_SESSION_DURATION = 14400;
const twilioAccountSid = process.env.TWILIO_ACCOUNT_SID;
const twilioApiKeySID = process.env.TWILIO_API_KEY_SID;
const twilioApiKeySecret = process.env.TWILIO_API_KEY_SECRET;
app.use(express.static(path.join(__dirname, 'build')));
app.get('/token', (req, res) => {
const { identity, roomName } = req.query;
const token = new AccessToken(twilioAccountSid, twilioApiKeySID, twilioApiKeySecret, {
ttl: MAX_ALLOWED_SESSION_DURATION,
});
token.identity = identity;
const videoGrant = new VideoGrant({ room: roomName });
token.addGrant(videoGrant);
res.send(token.toJwt());
console.log(`issued token for ${identity} in room ${roomName}`);
});
app.get('*', (_, res) => res.sendFile(path.join(__dirname, 'build/index.html')));
app.listen(8081, () => console.log('token server running on 8081'));
I'm thinking I can move that to the cloud functions index.js file and add the following to still connect to my .env file variables if I put the express function in here:
const functions = require('firebase-functions');
const config = functions.config();
// Porting envs from firebase config
for (const key in config.envs){
process.env[key.toUpperCase()] = config.envs[key];
}
To convert this to a Firebase cloud function, you need to remove server listeners and you have to setup a local Firebase environment to deploy and develop
Steps to convert cloud function
# Install firebase-tools
npm install -g firebase-tools
# Login and initialize project
firebase login
firebase init functions
# For local dev
firebase serve
# Deploy the function to cloud
firebase deploy
Your current code will look something like this after converting to cloud function
You can also make each routes into separate modules
const functions = require('firebase-functions');
const express = require('express');
const app = express();
const path = require('path');
const AccessToken = require('twilio').jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;
require('dotenv').config();
const router = express.Router();
const MAX_ALLOWED_SESSION_DURATION = 14400;
const twilioAccountSid = process.env.TWILIO_ACCOUNT_SID;
const twilioApiKeySID = process.env.TWILIO_API_KEY_SID;
const twilioApiKeySecret = process.env.TWILIO_API_KEY_SECRET;
app.use(express.static(path.join(__dirname, 'build')));
router.get('/token', (req, res) => {
const { identity, roomName } = req.query;
const token = new AccessToken(twilioAccountSid, twilioApiKeySID, twilioApiKeySecret, {
ttl: MAX_ALLOWED_SESSION_DURATION,
});
token.identity = identity;
const videoGrant = new VideoGrant({ room: roomName });
token.addGrant(videoGrant);
res.send(token.toJwt());
console.log(`issued token for ${identity} in room ${roomName}`);
});
router.get('*', (_, res) => res.sendFile(path.join(__dirname, 'build/index.html')));
// Your cloud function will be like : https://<region>-<appname>.cloudfunctions.net/twilioApp
exports.twilioApp = functions.https.onRequest(router);
Please read the official documentation here

Resources