Repository: googleapis/google-cloud-python

Issue:
speech api with sample content bytes is not encoded to ASCII string before being sent over the wire
When using the package as under with python3.5 -

```
with open('linear.wav', 'rb') as f:
    data = f.read()

s = client.sample(data, None, encoding=Encoding.LINEAR16, sample_rate=16000)
texts = client.sync_recognize(s)
```

Throws an error that it is not possible to convert the byte stream to JSON.

In `speech/google/cloud/speech/client.py#240` the following line encodes the bytes in base64 but the return type of b64encode is still bytes.

```
audio = {'content': b64encode(_to_bytes(sample.content))}
```

If this is changed to the following, the API behaves as expected -

```
audio = {'content': b64encode(_to_bytes(sample.content)).decode('ascii')}
```

speech api with sample content bytes is not encoded to ASCII string before being sent over the wire
When using the package as under with python3.5 -

```
with open('linear.wav', 'rb') as f:
    data = f.read()

s = client.sample(data, None, encoding=Encoding.LINEAR16, sample_rate=16000)
texts = client.sync_recognize(s)
```

Throws an error that it is not possible to convert the byte stream to JSON.

In `speech/google/cloud/speech/client.py#240` the following line encodes the bytes in base64 but the return type of b64encode is still bytes.

```
audio = {'content': b64encode(_to_bytes(sample.content))}
```

If this is changed to the following, the API behaves as expected -

```
audio = {'content': b64encode(_to_bytes(sample.content)).decode('ascii')}
```



Discussion:
Thanks for reporting @INRIX-Avilay-Parekh!
I was able to reproduce this, thanks to your examples.

I'm working on a fix right now.

Thanks for reporting @INRIX-Avilay-Parekh!
I was able to reproduce this, thanks to your examples.

I'm working on a fix right now.


Resolving patch:
diff --git a/speech/google/cloud/speech/client.py b/speech/google/cloud/speech/client.py
--- a/speech/google/cloud/speech/client.py
+++ b/speech/google/cloud/speech/client.py
@@ -17,6 +17,7 @@
 from base64 import b64encode
 
 from google.cloud._helpers import _to_bytes
+from google.cloud._helpers import _bytes_to_unicode
 from google.cloud import client as client_module
 from google.cloud.speech.connection import Connection
 from google.cloud.speech.encoding import Encoding
@@ -237,7 +238,8 @@ def _build_request_data(sample, language_code=None, max_alternatives=None,
     :returns: Dictionary with required data for Google Speech API.
     """
     if sample.content is not None:
-        audio = {'content': b64encode(_to_bytes(sample.content))}
+        audio = {'content':
+                 _bytes_to_unicode(b64encode(_to_bytes(sample.content)))}
     else:
         audio = {'uri': sample.source_uri}
 


Test patch:
diff --git a/speech/unit_tests/test_client.py b/speech/unit_tests/test_client.py
--- a/speech/unit_tests/test_client.py
+++ b/speech/unit_tests/test_client.py
@@ -61,13 +61,15 @@ def test_create_sample_from_client(self):
         self.assertEqual(content_sample.encoding, Encoding.FLAC)
 
     def test_sync_recognize_content_with_optional_parameters(self):
-        import base64
+        from base64 import b64encode
         from google.cloud._helpers import _to_bytes
+        from google.cloud._helpers import _bytes_to_unicode
+
         from google.cloud.speech.encoding import Encoding
         from google.cloud.speech.sample import Sample
         from unit_tests._fixtures import SYNC_RECOGNIZE_RESPONSE
-
-        _B64_AUDIO_CONTENT = base64.b64encode(_to_bytes(self.AUDIO_CONTENT))
+        _AUDIO_CONTENT = _to_bytes(self.AUDIO_CONTENT)
+        _B64_AUDIO_CONTENT = _bytes_to_unicode(b64encode(_AUDIO_CONTENT))
         RETURNED = SYNC_RECOGNIZE_RESPONSE
         REQUEST = {
             'config': {