diff --git a/record-and-playback/core/lib/recordandplayback/edl/audio.rb b/record-and-playback/core/lib/recordandplayback/edl/audio.rb
index e6c500c0d87764da1697eb6ab46b9af77d95c1b8..e5758a28150f56d630dfaab40f6a6af1779a1057 100644
--- a/record-and-playback/core/lib/recordandplayback/edl/audio.rb
+++ b/record-and-playback/core/lib/recordandplayback/edl/audio.rb
@@ -42,7 +42,6 @@ module BigBlueButton
       end
 
       def self.render(edl, output_basename)
-        sections = []
         audioinfo = {}
 
         corrupt_audios = Set.new
@@ -61,13 +60,14 @@ module BigBlueButton
         audioinfo.keys.each do |audiofile|
           BigBlueButton.logger.debug "  #{audiofile}"
           info = audio_info(audiofile)
-          BigBlueButton.logger.debug "    sample rate: #{info[:sample_rate]}, duration: #{info[:duration]}"
-
           if !info[:audio] || !info[:duration]
             BigBlueButton.logger.warn "    This audio file is corrupt! It will be removed from the output."
             corrupt_audios << audiofile
           end
 
+          BigBlueButton.logger.debug "    format: #{info[:format][:format_name]}, codec: #{info[:audio][:codec_name]}"
+          BigBlueButton.logger.debug "    sample rate: #{info[:sample_rate]}, duration: #{info[:duration]}"
+
           audioinfo[audiofile] = info
         end
 
@@ -82,70 +82,60 @@ module BigBlueButton
           dump(edl)
         end
 
-        input_index = 0
-        output_index = 0
         ffmpeg_inputs = []
-        ffmpeg_filters = []
+        ffmpeg_filter = ''
         BigBlueButton.logger.info "Generating ffmpeg command"
         for i in 0...(edl.length - 1)
           entry = edl[i]
           audio = entry[:audio]
           duration = entry[:next_timestamp] - entry[:timestamp]
 
-          # Check for and handle audio files with mismatched lengths (generated
-          # by buggy versions of freeswitch in old BigBlueButton
-          if audio and entry[:original_duration] and
-               (audioinfo[audio[:filename]][:duration].to_f / entry[:original_duration]) < 0.997 and
-               ((entry[:original_duration] - audioinfo[audio[:filename]][:duration]).to_f /
-                      entry[:original_duration]).abs < 0.05
-            speed = audioinfo[audio[:filename]][:duration].to_f / entry[:original_duration]
-            BigBlueButton.logger.info "  Using input #{audio[:filename]}"
+          ffmpeg_filter << "[a_edl#{i}_prev];\n" if i > 0
 
-            BigBlueButton.logger.warn "  Audio file length mismatch, adjusting speed to #{speed}"
-
-            # Have to calculate the start point after the atempo filter in this case,
-            # since it can affect the audio start time.
-            # Also reset the pts to start at 0, so the duration trim works correctly.
-            filter = "[#{input_index}] "
-            filter << "atempo=#{speed},atrim=start=#{ms_to_s(audio[:timestamp])},"
-            filter << "asetpts=PTS-STARTPTS,"
-            filter << "#{FFMPEG_AFORMAT},apad,atrim=end=#{ms_to_s(duration)} [out#{output_index}]"
-            ffmpeg_filters << filter
-
-            ffmpeg_inputs << {
-              :filename => audio[:filename],
-              :seek => 0
-            }
-
-            input_index += 1
-            output_index += 1
-
-            # Normal audio input handling. Skip this input and generate silence
-            # if the seekpoint is past the end of the audio, which can happen
-            # if events are slightly misaligned and you get unlucky with a
-            # start/stop or chapter break.
-          elsif audio and audio[:timestamp] < audioinfo[audio[:filename]][:duration]
+          if audio
             BigBlueButton.logger.info "  Using input #{audio[:filename]}"
 
-            filter = "[#{input_index}] "
-            filter << "#{FFMPEG_AFORMAT},apad,atrim=end=#{ms_to_s(duration)} [out#{output_index}]"
-            ffmpeg_filters << filter
+            speed = 1
+            seek = audio[:timestamp]
 
-            ffmpeg_inputs << {
-              :filename => audio[:filename],
-              :seek => audio[:timestamp]
-            }
+            # Check for and handle audio files with mismatched lengths (generated
+            # by buggy versions of freeswitch in old BigBlueButton
+            if entry[:original_duration] && (audioinfo[audio[:filename]][:duration].to_f / entry[:original_duration]) < 0.997 &&
+               ((entry[:original_duration] - audioinfo[audio[:filename]][:duration]).to_f /
+                      entry[:original_duration]).abs < 0.05
+              BigBlueButton.logger.warn "  Audio file length mismatch, adjusting speed to #{speed}"
+              speed = audioinfo[audio[:filename]][:duration].to_f / entry[:original_duration]
+              seek = 0
+            end
+
+            # Skip this input and generate silence if the seekpoint is past the end of the audio, which can happen
+            # if events are slightly misaligned and you get unlucky with a start/stop or chapter break.
+            if audio[:timestamp] < (audioinfo[audio[:filename]][:duration] * speed)
+              input_index = ffmpeg_inputs.length
+              ffmpeg_inputs << {
+                filename: audio[:filename],
+                seek: seek
+              }
+              ffmpeg_filter << "[#{input_index}]#{FFMPEG_AFORMAT},apad"
+            else
+              ffmpeg_filter << "#{FFMPEG_AEVALSRC},#{FFMPEG_AFORMAT}"
+            end
 
-            input_index += 1
-            output_index += 1
+            ffmpeg_filter << ",atempo=#{speed},atrim=start=#{ms_to_s(audio[:timestamp])}" if speed != 1
 
+            ffmpeg_filter << ",asetpts=PTS-STARTPTS"
           else
             BigBlueButton.logger.info "  Generating silence"
 
-            ffmpeg_filters << "#{FFMPEG_AEVALSRC},#{FFMPEG_AFORMAT},atrim=end=#{ms_to_s(duration)} [out#{output_index}]"
+            ffmpeg_filter << "#{FFMPEG_AEVALSRC},#{FFMPEG_AFORMAT}"
+          end
 
-            output_index += 1
+          if i > 0
+            ffmpeg_filter << "[a_edl#{i}];\n"
+            ffmpeg_filter << "[a_edl#{i}_prev][a_edl#{i}]concat=n=2:a=1:v=0"
           end
+
+          ffmpeg_filter << ",atrim=end=#{ms_to_s(entry[:next_timestamp])}"
         end
 
         ffmpeg_cmd = [*FFMPEG]
@@ -157,19 +147,15 @@ module BigBlueButton
           end
           ffmpeg_cmd += ['-i', input[:filename]]
         end
-        ffmpeg_filter = ffmpeg_filters.join(' ; ')
-
-        if output_index > 1
-          # Add the final concat filter
-          ffmpeg_filter << " ; "
-          (0...output_index).each { |i| ffmpeg_filter << "[out#{i}]" }
-          ffmpeg_filter << " concat=n=#{output_index}:a=1:v=0"
-        else
-          # Only one input, no need for concat filter
-          ffmpeg_filter << " ; [out0] anull"
+
+        BigBlueButton.logger.debug('  ffmpeg filter_complex_script:')
+        BigBlueButton.logger.debug(ffmpeg_filter)
+        filter_complex_script = "#{output_basename}.filter"
+        File.open(filter_complex_script, 'w') do |io|
+          io.write(ffmpeg_filter)
         end
 
-        ffmpeg_cmd += ['-filter_complex', ffmpeg_filter]
+        ffmpeg_cmd << '-filter_complex_script' << filter_complex_script
 
         output = "#{output_basename}.#{WF_EXT}"
         ffmpeg_cmd += [*FFMPEG_WF_ARGS, output]