Search code examples
ruby-on-railsaudio

Rails: Save Audio from Byte Stream to ActiveStorage as MP3


I am using a text-to-voice API in my Rails 7 app and am having translation issues.

So far, I have successfully gotten the API to respond 200 (and I have checked with Insomnia and the preview yields the correct preview of the audio file). So that much I know works.

However, the output is coming out as a binary byte stream (I think), so the raw data I'm getting as my response.read_body is a lovely:

ID3#TSSELavf58.29.100����]D:�)�ķ�L�5A��@7
2�L��3��8�ֳYKFY�@G-�(    ���"�w��D@c�;a�S��-"
:���&"�X�Ac���؛���{b�v1p���3�-�kn[[k�[���!�r���w�;gm}�rܷ-�g
q�9C8r���ܷ-��o���������v�q�vܷ��ݷ-�r����!����vܷ����q�r����q�v������m����rÐ�9
}�rܷ-�kn[��?���9C��9n[����������Ð��8kC_gn[[gl흳����p��8r�q��n[��ܷ-�������]��1����gl=���v�؃8g�3�p��;gl흳�v���_�c�.�1���0���"0H� �F0    ��T:B0��l4CSg4`�g6�÷8y��Gg2�"�@1����`�DT`�8(D�<Z����^mL9���\Hdf:8c&.ahH5��=i#"HL�D�4�ω�)���(����i�c�DI��tJ��4�L)-:�.���)�h�Ò����hXj�]�EVrn/�,�Д�L]�n����"�ր�Iȴ^�(P��b$S4�G��^x":�/
���m#�`��   �_�:#d2��,�SGZ��F��}��(�3=�C�����R��L�zap:=/������e�5>��ח��g���_8O̭j�2h
��W��h����-iC:^/,��S�
�]#��w�hc>i�֓%~��̒,����Sf���Ii0&���r�+XU��Wj��UL��2�T���2�*f�&�C�@.�3���H>��9�Ѕ �I�@@�04D�<��i�WH�X�@�ä8L&�������E3hXT��:D�\De����DŽ�����l� f�I��F3���%(șFf����{q�2�0�&��k��f�O�8i��~���`0d�����
\�c�9���V

(Only...a lot more of it...)

Now I'm trying to save this as an mp3 file as an ActiveStorage attachment...which is where things are going badly.

Here's the code I currently have in my message.rb method:

  def get_audio

    ... 
    (THIS PART IS JUST THE API REQUEST...WHICH WORKS)
    ... 

    response = http.request(request)

    if response.code == "200"
      result = response.read_body
      puts result  <<<<<THIS PART YIELDS THE BINARY
      self.audio_data.attach(result)
    else
      Rerecord.create(message_id: self.id)
      puts "ERROR!!!"
    end 

  end

Right now this errors with a ActiveSupport::MessageVerifier::InvalidSignature - mismatched digest error on the line where I try to attach it.

I've looked at a bunch of other SO posts (this was closest, but was JS not Ruby) but nothing seems to be what I need. Has anyone done this successfully?


Solution

  • Okay, I got a lot of help from someone WAY smarter than I am, but the eventual verdict was that I had to temporarily save it as a file before I attached it with ActiveStorage.

    Here's the code that ended up working:

    response = http.request(request)
    
    if response.code == "200"
      result = response.read_body
      audio_data = response.body
    
      save_path = 'lib/'
      filename = "Message-#{self.id}.mp3"
      filepath = "#{save_path}/#{filename}"
      File.open(filepath, 'wb') { |f| f.write audio_data }
      self.audio_data.attach(io: open(filepath), filename: filename)
      File.delete(filepath)
    else
      Rerecord.create(message_id: self.id)
      puts "ERROR!!!"
    end 
    

    Hope this saves someone else the time it took to get this fixed!