When a recording ends, that worker is getting two messages. The first contains the raw data buffer (what you really want). The second contains the processed WAV, a binary object which can't be directly serialized to JSON. If you check Shiny's trace logs, it's being sent as an empty object. I think you really just want to not export that WAV.
I poked around to see what runs when the recording stops.
https://github.com/ropensci/googleLanguageR/blob/shiny-demo/inst/shiny/capture_speech/www/main.js#L57-L61
https://github.com/ropensci/googleLanguageR/blob/shiny-demo/inst/shiny/capture_speech/www/main.js#L41-L49
I can't confirm if this works, but try placing the Shiny.onInputChange here and taking out the exportWAV.
function gotBuffers( buffers ) {
var canvas = document.getElementById( "wavedisplay" );
drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );
// the ONLY time gotBuffers is called is right after a new recording is completed -
// so here's where we should set up the download.
// audioRecorder.exportWAV( doneEncoding );
Shiny.onInputChange("audio", buffers);
}