2

I am busy writing a Google cloud function that gets activated by a Google Cloud Storage activity. I need to use sox in a child_process - but not having much success.

This function picks up the audio file/event and then needs to calculate the length of the file and then display that.

When i run the following code(in my index.js):

'use strict';

const exec = require('child_process').exec;
const fs = require('fs');
const path = require('path');
const storage = require('@google-cloud/storage')();
const vision = require('@google-cloud/vision').v1p1beta1;

const client = new vision.ImageAnnotatorClient();


exports.processAudiofile = (event) => {
  const object = event.data;

  if (object.resourceState === 'not_exists') {
    console.log('This is a deletion event.');
    return;
  } else if (!object.name) {
    console.log('This is a deploy event.');
    return;
  }

  const file = storage.bucket(object.bucket).file(object.name);
  const filePath = `gs://${object.bucket}/${object.name}`;

  console.log(`Analyzing ${file.name}.`);
  console.log(`Filepath is ${filePath}.`);

  return new Promise((resolve, reject) => {
    exec(`sox --i -d ${filePath}`, function(err, stdout){
        if (err){
             throw err;
    }
    console.log("Duration:" + stdout);//Prints
    });
  });

};

with the following package.json:

{
  "name": "audiotest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@google-cloud/language": "^1.2.0",
    "@google-cloud/speech": "^1.5.0",
    "@google-cloud/storage": "^1.6.0",
    "@google-cloud/vision": "^0.19.0",
    "child_process": "^1.0.2",
    "fs": "0.0.1-security",
    "got": "^8.3.1",
    "path": "^0.12.7",
    "sox": "^0.1.0"
  }
}

i get the following error:

Error: Command failed: sox --i -d gs://rawaudiobucket/shortcall.wav 
/bin/sh: 1: sox: not found at ChildProcess.exithandler 
(child_process.js:199:12) at emitTwo (events.js:106:13) at 
ChildProcess.emit (events.js:191:7) at maybeClose 
(internal/child_process.js:920:16) at Socket.<anonymous> 
(internal/child_process.js:351:11) at emitOne (events.js:96:13) at 
Socket.emit (events.js:188:7) at Pipe._handle.close [as _onclose] 
(net.js:509:12)

Any help on this would be greatly appreciated!

JanCN
  • 21
  • 3

1 Answers1

0

It looks like you're assuming that sox is available as a command line program in the instances that run Cloud Functions. Unless that particular program has been documented be presently (like ImageMagic convert), you shouldn't depend on it.

Note that the npm page for the sox module says:

Requires sox CLI to be installed. This can be installed via most linux distribution's package managers.

If you provide your own Linux-compiled binary, you may be able to execute it directly. Getting that to build and run via the node module is going to be its own issue.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Thanks for the feedback doug! So, if i understand you correctly - since sox doesnt seem to work - it means that the vm that gets created when the function is triggered doesnt contain sox? And in short - i cant use sox on google functions yet? What would a workaround be if i still waned to use the elegance and serverless options that google functions offer? – JanCN May 20 '18 at 20:41
  • Another question on this : does the fact that i specify sox in the package.json file not by default install the module on the vm that is created for the function? – JanCN May 20 '18 at 20:53
  • If you have a followup question that's different than the first one, please ask it separately. – Doug Stevenson May 21 '18 at 14:21
  • @JanCN the packages installed by npm are node packages that might rely on system binaries to run properly (they are just wrappers), so you still need the binaries to be installed by google beforehand, you can't do this yourself – Mischa Molhoek Jan 07 '19 at 07:41