diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index 622dedeebb0eba8c3006d7f8c81bed0bf883364a..7a0b5fe51334c5c8b9f52fbb89e462430cf14f85 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -300,42 +300,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
         frame->key_frame = 0;
     }
 
-    AVPacket pkt;
-    memset(&pkt, 0, sizeof(pkt));
-    av_init_packet(&pkt);
-
-    int ret = 0;
-    ret = avcodec_send_frame(encoderCtx_, frame);
-    if (ret < 0)
-        return -1;
-
-    while (1) {
-        ret = avcodec_receive_packet(encoderCtx_, &pkt);
-        if (ret == AVERROR(EAGAIN))
-            break;
-        if (ret < 0)
-            return -1;
-
-        if (pkt.size) {
-            if (pkt.pts != AV_NOPTS_VALUE)
-                pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
-                                       stream_->time_base);
-            if (pkt.dts != AV_NOPTS_VALUE)
-                pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
-                                       stream_->time_base);
-
-            pkt.stream_index = stream_->index;
-
-            // write the compressed frame
-            ret = av_write_frame(outputCtx_, &pkt);
-            if (ret < 0) {
-                RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
-            } else
-                break;
-        }
-    }
-
-    av_packet_unref(&pkt);
+    int ret = encode(frame, stream_->index);
 
     return ret;
 }
@@ -368,7 +333,7 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
     const auto sample_rate = buffer.getSampleRate();
 
     while (nb_frames > 0) {
-        AVFrame *frame = av_frame_alloc();
+        AVFrame* frame = av_frame_alloc();
         if (!frame)
             return -1;
 
@@ -394,8 +359,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
                                            reinterpret_cast<const uint8_t *>(offset_ptr),
                                            buffer_size, 0);
         if (err < 0) {
-            RING_ERR("Couldn't fill audio frame: %s: %d %d", libav_utils::getError(err).c_str(),
-                     frame->nb_samples, buffer_size);
+            RING_ERR() << "Failed to fill audio frame of size" << buffer_size << " with "
+                << frame->nb_samples << " samples: " << libav_utils::getError(err);
             av_frame_free(&frame);
             return -1;
         }
@@ -403,66 +368,35 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
         nb_frames -= frame->nb_samples;
         offset_ptr += frame->nb_samples * buffer.channels();
 
-        AVPacket pkt;
-        av_init_packet(&pkt);
-        pkt.data = NULL; // packet data will be allocated by the encoder
-        pkt.size = 0;
-        int ret = 0;
-
-        ret = avcodec_send_frame(encoderCtx_, frame);
-        if (ret < 0)
-            return -1;
-
-        while (1) {
-            ret = avcodec_receive_packet(encoderCtx_, &pkt);
-            if (ret == AVERROR(EAGAIN))
-                break;
-            if (ret < 0)
-                return -1;
-
-            if (pkt.size) {
-                if (pkt.pts != AV_NOPTS_VALUE)
-                    pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
-                                           stream_->time_base);
-                if (pkt.dts != AV_NOPTS_VALUE)
-                    pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
-                                           stream_->time_base);
-
-                pkt.stream_index = stream_->index;
-
-                // write the compressed frame
-                ret = av_write_frame(outputCtx_, &pkt);
-                if (ret < 0) {
-                    RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
-                } else
-                    break;
-            }
-        }
-
-        av_packet_unref(&pkt);
+        encode(frame, stream_->index);
         av_frame_free(&frame);
     }
 
     return 0;
 }
 
-int MediaEncoder::flush()
+int
+MediaEncoder::encode(AVFrame* frame, int streamIdx)
 {
+    int ret = 0;
     AVPacket pkt;
-    memset(&pkt, 0, sizeof(pkt));
     av_init_packet(&pkt);
+    pkt.data = NULL; // packet data will be allocated by the encoder
+    pkt.size = 0;
+    pkt.stream_index = streamIdx;
 
-    int ret = 0;
-    ret = avcodec_send_frame(encoderCtx_, nullptr);
+    ret = avcodec_send_frame(encoderCtx_, frame);
     if (ret < 0)
         return -1;
 
-    while (1) {
+    while (ret >= 0) {
         ret = avcodec_receive_packet(encoderCtx_, &pkt);
         if (ret == AVERROR(EAGAIN))
             break;
-        if (ret < 0)
-            return -1;
+        if (ret < 0) {
+            RING_ERR() << "Failed to encode frame: " << libav_utils::getError(ret);
+            return ret;
+        }
 
         if (pkt.size) {
             if (pkt.pts != AV_NOPTS_VALUE)
@@ -472,19 +406,24 @@ int MediaEncoder::flush()
                 pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
                                        stream_->time_base);
 
-            pkt.stream_index = stream_->index;
 
             // write the compressed frame
             ret = av_write_frame(outputCtx_, &pkt);
             if (ret < 0) {
-                RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
+                RING_ERR() << "av_write_frame failed: " << libav_utils::getError(ret);
             } else
                 break;
         }
     }
+
     av_packet_unref(&pkt);
+    return 0;
+}
 
-    return ret;
+int
+MediaEncoder::flush()
+{
+    return encode(nullptr, stream_->index);
 }
 
 std::string
diff --git a/src/media/media_encoder.h b/src/media/media_encoder.h
index 68285280a71a80241949b9e9f8d2458a03d240ca..44e824411844bea3c630ffb262b5819c48bffab8 100644
--- a/src/media/media_encoder.h
+++ b/src/media/media_encoder.h
@@ -72,6 +72,10 @@ public:
 #endif // RING_VIDEO
 
     int encode_audio(const AudioBuffer &input);
+
+    // frame should be ready to be sent to the encoder at this point
+    int encode(AVFrame* frame, int streamIdx);
+
     int flush();
     std::string print_sdp();