Save Google Cloud Speech API operation(job) object to retrieve results later

494 views Asked by At

I'm struggling to use the Google Cloud Speech Api with the ruby client (v0.22.2).

I can execute long running jobs and can get results if I use

job.wait_until_done!

but this locks up a server for what can be a long period of time.

According to the API docs, all I really need is the operation name(id).

Is there any way of creating a job object from the operation name and retrieving it that way? I can't seem to create a functional new job object such as to use the id from @grpc_op

What I want to do is something like:

speech = Google::Cloud::Speech.new(auth_credentials)
job = speech.recognize_job file, options

saved_job = job.to_json #Or some element of that object such that I can retrieve it.

Later, I want to do something like....
job_object = Google::Cloud::Speech::Job.new(saved_job)

job.reload!

job.done?

job.results

Really hoping that makes sense to somebody. Struggling quite a bit with google's ruby clients on the basis that everything seems to be translated into objects which are much more complex than the ones required to use the API. Is there some trick that I'm missing here?

2

There are 2 answers

3
blowmage On BEST ANSWER

You can monkey-patch this functionality to the version you are using, but I would advise upgrading to google-cloud-speech 0.24.0 or later. With those more current versions you can use Operation#id and Project#operation to accomplish this.

require "google/cloud/speech"

speech = Google::Cloud::Speech.new

audio = speech.audio "path/to/audio.raw",
                     encoding: :linear16,
                     language: "en-US",
                     sample_rate: 16000

op = audio.process
# get the operation's id
id = op.id #=> "1234567890"

# construct a new operation object from the id
op2 = speech.operation id

# verify the jobs are the same
op.id == op2.id #=> true

op2.done? #=> false
op2.wait_until_done!
op2.done? #=> true

results = op2.results

Update Since you can't upgrade, you can monkey-patch this functionality to an older-version using the workaround described in GoogleCloudPlatform/google-cloud-ruby#1214:

require "google/cloud/speech"

# Add monkey-patches
module Google
  Module Cloud
    Module Speech
      class Job
        def id
          @grpc.name
        end
      end
      class Project
        def job id
          Job.from_grpc(OpenStruct.new(name: id), speech.service).refresh!
        end
      end
    end
  end
end

# Use the new monkey-patched methods
speech = Google::Cloud::Speech.new

audio = speech.audio "path/to/audio.raw",
                     encoding: :linear16,
                     language: "en-US",
                     sample_rate: 16000

job = audio.recognize_job
# get the job's id
id = job.id #=> "1234567890"

# construct a new operation object from the id
job2 = speech.job id

# verify the jobs are the same
job.id == job2.id #=> true

job2.done? #=> false
job2.wait_until_done!
job2.done? #=> true

results = job2.results
0
Carpela On

Ok. Have a very ugly way of solving the issue.

Get the id of the Operation from the job object

operation_id = job.grpc.grpc_op.name

Get an access token to manually use the RestAPI

json_key_io = StringIO.new(ENV["GOOGLE_CLOUD_SPEECH_JSON_KEY"])
authorisation = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io:json_key_io,
  scope:"https://www.googleapis.com/auth/cloud-platform"
)
token = authorisation.fetch_access_token!

Make an api call to retrieve the operation details.

This will return with a "done" => true parameter, once results are in and will display the results. If "done" => true isn't there then you'll have to poll again later until it is.

HTTParty.get(
  "https://speech.googleapis.com/v1/operations/#{operation_id}",
  headers: {"Authorization" => "Bearer #{token['access_token']}"}
)

There must be a better way of doing that. Seems such an obvious use case for the speech API.

Anyone from google in the house who can explain a much simpler/cleaner way of doing it?