llfbandit / record

Audio recorder from microphone to a given file path. No external dependencies, MediaRecorder is used for Android an AVAudioRecorder for iOS.
https://pub.dev/packages/record
233 stars 196 forks source link

[web] Blob URL mime type is `application/octet-stream` with all encoders on Safari #376

Closed reza00farjam closed 1 month ago

reza00farjam commented 1 month ago

Package version 5.1.2

Environment

Describe the bug

No matter which encoder is set, in production the output of recorder on Safari would always have application/octet-stream as its mime type.

const RecordConfig(
  autoGain: true,
  echoCancel: true,
  noiseSuppress: true,
  encoder: AudioEncoder.aacLc,
),

Expected behavior

The outputed Blob URL should have the mime type corresponding to the selected encoder, in this case audio/mp4.

reza00farjam commented 1 month ago

After some days of research and testing, I finally came across an answer (not a solution sadly).

Long story short, this behavior is because of the Safari browser privacy.

Based on what I found, Safari won't let clients to download any file except for Images and PDFs. So, basically in web and in case of uploading recorded audio Blob (which is what stop method returns) to your server, you need to download the recoding first and read it as bytes. It doesn't matter if you use http or dio packages, or do it using cross_file package, or even download it with pure html. It always going to end up in an error and your received bytes would be a file containing that error and not an actual audio file. And the application/octet-stream mime type was right, it was always a file and not an audio file.

Then I think of using startStream instead of start method, because it gave you bytes of recording in real-time instead of recording Blob URL at the end of the session. In theory it should have been worked, but surprisingly in action I observed that on Safari no bytes were streaming at all to use.

I leave this issue open in hope of some one corrects me and gave us a solution. Or at least add a warning in package info about this limitations on Safari browser.

Thanks!

dhruvin-rv commented 1 month ago

As I was also facing the same issue and there is no other solution in safari for this i finally decided to send the application/octet-stream to the backend server and converted it to the required codec using FFMPEG which i think the best solution to handle this kind of requirement.

reza00farjam commented 1 month ago

Thank you @dhruvin-rv for sharing your experience. In my case the application/octet-stream wasn't decodable, in fact it was an error file or something like that. Are you sure in your case the FFMPEG converted output was an audio file? If yes, can you please share your back-end part code for reference? Thanks.

llfbandit commented 1 month ago

Released in record_web 1.1.3

reza00farjam commented 1 month ago

@llfbandit thank you for the fix. How can we use this new web version while the main package is not updated yet. Should we use record_web in project pubspec.yaml instead of record package itself?

llfbandit commented 1 month ago

Just use flutter pub upgrade