1
votes

here is the Context : My iOS swift app

  1. records a sound,
  2. creates a firebase object,
  3. renames the file with the key of the object
  4. uploads on firebase cloud the wav file.
  5. A firebase cloud function is triggered that sends the audio file to google speech .recognize

My problem : When I upload manually a sound file to the cloud storage, it works fine, but when the file is uploaded by the app automatically, I get the following error message as a return form the speech API :

{ Error: The caller does not have permission
at /user_code/node_modules/@google-cloud/speech/node_modules/grpc/src/node/src/client.js:554:15

code: 7, metadata: Metadata { _internal_repr: {} }, note: 'Exception occurred in retry method that was not classified as transient' }

Here is the swift part :

func uploadFile(fileName:String){

    // File located on disk
    let localFileURL = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask)[0]
    let fileURL = localFileURL.appendingPathComponent(fileName)
    if FileManager.default.fileExists(atPath: fileURL.path) {
        print("FilePath", fileURL.path)
        // Create a reference to the file you want to upload
        let newMnemoRef = MnemoDatabase.shared.createNew()

        let newMnemoId = newMnemoRef.key
        let filename=newMnemoId+".wav"
        //let filename=fileName
        let audioStorageRef = storage.reference().child(filename)
        let storagePath = "gs://\(audioStorageRef.bucket)/\(audioStorageRef.fullPath)"

        print(storagePath)
        // Upload the file to the path "audio"
        let uploadTask = audioStorageRef.putFile(from: fileURL, metadata: nil) { metadata, error in
            if let error = error {
                print("Upload error : ", error.localizedDescription)
            } else {
                // Metadata contains file metadata such as size, content-type, and download URL.
                print ("OK")

            }
        }

        // Add a progress observer to an upload task
        let observer = uploadTask.observe(.success) { snapshot in
            print("uploaded!")
            newMnemoRef.child("audio").setValue([
                "encoding_converted":"LINEAR16",
                "sampleRate_converted":"44100",
                "path_converted":storagePath])

        }


    } else {
        print ("Non existent file", fileURL.path)
    }

}

The cloud function calling the the speech API is fine with manually uploaded files. here is the extract

const request = {
      encoding: encoding,
      sampleRateHertz: sampleRateHertz,
      languageCode: language,
      speechContexts: context

    };
speech.recognize(uri, request)

The cloud storage bucket and cloud function all share the same project credentials. I removed all authentification from the bucket

// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with Google App Engine, this will also make
// files uploaded via GAE public.
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}

I even tried hard coding the path into the cloud function, but to no avail.

I will appreciate any help

1

1 Answers

0
votes

Well it seems that I was working on two different projects, and the one I was calling functions from didn't have the speech API activated, and I was passing credentials of the other project. I should really stop working too late... I re-engineered my project to work with a file trigger now, this is how I found the bug...