diff --git a/akka-bbb-apps/src/main/resources/application.conf b/akka-bbb-apps/src/main/resources/application.conf
index d7c9e9de65e0ce81f0617005683a8521b4433279..4de5614cf646452585c96d770d4c5e3760059cb2 100755
--- a/akka-bbb-apps/src/main/resources/application.conf
+++ b/akka-bbb-apps/src/main/resources/application.conf
@@ -82,4 +82,8 @@ services {
 
 apps {
   checkPermissions = true
+}
+
+voiceConf {
+  recordPath = "/var/freeswitch/meetings"
 }
\ No newline at end of file
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index fc337002501963a40e570234b01b9f10766ee37a..840843e845d935893f883da3407eada1e9be54ae 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -61,4 +61,6 @@ trait SystemConfiguration {
   lazy val telizePort = Try(config.getInt("services.telizePort")).getOrElse(80)
 
   lazy val applyPermissionCheck = Try(config.getBoolean("apps.checkPermissions")).getOrElse(false)
+
+  lazy val voiceConfRecordPath = Try(config.getString("voiceConf.recordPath")).getOrElse("/var/freeswitch/meetings")
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
index 7c262c2bc7abbde94edb0585629c8050559e9952..8b1c4cdf49bdf76dbe4655c51030997cbe6a0fec 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
@@ -1,13 +1,15 @@
 package org.bigbluebutton.core.apps.voice
 
+import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.apps.breakout.BreakoutHdlrHelpers
 import org.bigbluebutton.core.models.{ VoiceUserState, VoiceUsers }
 import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
+import org.bigbluebutton.core.util.TimeUtil
 import org.bigbluebutton.core2.MeetingStatus2x
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
-trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
+trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers with SystemConfiguration {
   this: BaseMeetingActor =>
 
   val liveMeeting: LiveMeeting
@@ -62,9 +64,11 @@ trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
       liveMeeting.props.recordProp.record &&
       !MeetingStatus2x.isVoiceRecording(liveMeeting.status)) {
 
-      log.info("Send START RECORDING voice conf. meetingId=" + liveMeeting.props.meetingProp.intId
-        + " voice conf=" + liveMeeting.props.voiceProp.voiceConf)
-      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW)
+      val meetingId = liveMeeting.props.meetingProp.intId
+      val recordFile = VoiceApp.genRecordPath(voiceConfRecordPath, meetingId, TimeUtil.timeNowInMs())
+      log.info("Send START RECORDING voice conf. meetingId=" + meetingId + " voice conf=" + liveMeeting.props.voiceProp.voiceConf)
+
+      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW, recordFile)
     } else {
       log.info("Not recording audio as numVoiceUsers={} and isRecording={} and recordProp={}", numVoiceUsers,
         MeetingStatus2x.isVoiceRecording(liveMeeting.status), liveMeeting.props.recordProp.record)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
index 2d4dc81352f0cd658600c1bf9919984fde93f87c..bc56c5163e87dcf8c3eceb7485e9b0f6b6086658 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
@@ -1,16 +1,27 @@
 package org.bigbluebutton.core.apps.voice
 
+import java.io.File
+
 import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
 import org.bigbluebutton.core2.MeetingStatus2x
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
 object VoiceApp {
 
-  def startRecordingVoiceConference(liveMeeting: LiveMeeting, outGW: OutMsgRouter): Unit = {
+  def genRecordPath(recordDir: String, meetingId: String, timestamp: Long): String = {
+    if (recordDir.endsWith("/")) {
+      recordDir.concat(meetingId).concat("-").concat(timestamp.toString).concat(".wav")
+    } else {
+      recordDir.concat("/").concat(meetingId).concat("-").concat(timestamp.toString).concat(".wav")
+    }
+  }
+
+  def startRecordingVoiceConference(liveMeeting: LiveMeeting, outGW: OutMsgRouter, stream: String): Unit = {
     MeetingStatus2x.startRecordingVoice(liveMeeting.status)
     val event = MsgBuilder.buildStartRecordingVoiceConfSysMsg(
       liveMeeting.props.meetingProp.intId,
-      liveMeeting.props.voiceProp.voiceConf
+      liveMeeting.props.voiceProp.voiceConf,
+      stream
     )
     outGW.send(event)
   }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
index 26c19d21102c172ff2237018710b3158da5c0beb..0d79d2ab79dff29add0f0a6d80c6178178582228 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
@@ -136,6 +136,8 @@ class ReceivedJsonMsgHandlerActor(
         routeVoiceMsg[UserDisconnectedFromGlobalAudioMsg](envelope, jsonNode)
       case MuteMeetingCmdMsg.NAME =>
         routeGenericMsg[MuteMeetingCmdMsg](envelope, jsonNode)
+      case VoiceConfRunningEvtMsg.NAME =>
+        routeVoiceMsg[VoiceConfRunningEvtMsg](envelope, jsonNode)
 
       // Breakout rooms
       case BreakoutRoomsListMsg.NAME =>
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
index eb85c6584bcabe824bd2756f38b4f8a820c9a6ea..e9057b505fcb86f2abdda5b0886ff26c0711b455 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
@@ -19,6 +19,7 @@
 
 package org.bigbluebutton.core.record.events
 
+import java.text.SimpleDateFormat
 import java.util.Date
 
 import scala.collection.mutable.HashMap
@@ -34,7 +35,8 @@ trait RecordEvent {
 
   final def timestampUTC(utc: Long): Unit = {
     eventMap.put(TIMESTAMP_UTC, utc.toString)
-    eventMap.put(DATE, (new Date(utc)).toString)
+    val sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX")
+    eventMap.put(DATE, sdf.format(utc))
   }
 
   /**
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index e8d02e70a5f0d3b93ebe3bed197d974b79a37680..77886b21819187012e83666b387324e9a0fd6323 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -412,14 +412,17 @@ class MeetingActor(
     val now = TimeUtil.timeNowInMs()
     val elapsedInMs = now - lastRecBreakSentOn
     val elapsedInMin = TimeUtil.millisToMinutes(elapsedInMs)
-    println("******************* ElapsedInMS=" + elapsedInMs + ", elapsedInMIN=" + elapsedInMin)
+
     if (elapsedInMin > 1) {
       lastRecBreakSentOn = now
       val event = MsgBuilder.buildRecordingChapterBreakSysMsg(props.meetingProp.intId, TimeUtil.timeNowInMs())
       outGW.send(event)
 
       VoiceApp.stopRecordingVoiceConference(liveMeeting, outGW)
-      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW)
+
+      val meetingId = liveMeeting.props.meetingProp.intId
+      val recordFile = VoiceApp.genRecordPath(voiceConfRecordPath, meetingId, now)
+      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW, recordFile)
 
     }
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
index 64e41437b05f410e7b3953fc467f82796db08cae..f92d8f5b7e71272348d47677904d6b1c89d41a25 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
@@ -1,17 +1,21 @@
 package org.bigbluebutton.core.running
 
 import java.io.{ PrintWriter, StringWriter }
+import java.text.SimpleDateFormat
+import java.util.Date
 
 import akka.actor.Actor
 import akka.actor.ActorLogging
 import akka.actor.Props
 import akka.actor.OneForOneStrategy
 import akka.actor.SupervisorStrategy.Resume
+
 import scala.concurrent.duration._
 import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.domain.DefaultProps
 import org.bigbluebutton.core.api._
 import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, InternalEventBus }
+
 import scala.concurrent.ExecutionContext.Implicits.global
 
 object MeetingActorAudit {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
index 39ae45662f733483ee50888b69d1d9dd66669e1b..8ddf5eb3bd669c12c721e93b672301d0a7a3e5b8 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
@@ -258,11 +258,11 @@ object MsgBuilder {
     BbbCommonEnvCoreMsg(envelope, event)
   }
 
-  def buildStartRecordingVoiceConfSysMsg(meetingId: String, voiceConf: String): BbbCommonEnvCoreMsg = {
+  def buildStartRecordingVoiceConfSysMsg(meetingId: String, voiceConf: String, stream: String): BbbCommonEnvCoreMsg = {
     val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
     val envelope = BbbCoreEnvelope(StartRecordingVoiceConfSysMsg.NAME, routing)
     val header = BbbCoreHeaderWithMeetingId(StartRecordingVoiceConfSysMsg.NAME, meetingId)
-    val body = StartRecordingVoiceConfSysMsgBody(voiceConf, meetingId)
+    val body = StartRecordingVoiceConfSysMsgBody(voiceConf, meetingId, stream)
     val event = StartRecordingVoiceConfSysMsg(header, body)
     BbbCommonEnvCoreMsg(envelope, event)
   }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala
new file mode 100755
index 0000000000000000000000000000000000000000..a7349f270ecfba5f92039b3f71a18fc1f712f059
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala
@@ -0,0 +1,20 @@
+package org.bigbluebutton.core2.voiceconf
+
+import akka.actor.{ Actor, ActorLogging, FSM }
+import org.bigbluebutton.SystemConfiguration
+
+sealed trait VoiceConfState
+case object VoiceConfStarted extends VoiceConfState
+case object StartRecording extends VoiceConfState
+case object RecordingStarted extends VoiceConfState
+case object StopRecording extends VoiceConfState
+case object RecordingStopped extends VoiceConfState
+case object VoiceConfStopped extends VoiceConfState
+
+case class VoiceConfData(record: Boolean, numUsers: Int, streams: Vector[RecordStream])
+case class RecordStream(stream: String, started: Boolean)
+
+class VoiceConfActor extends Actor with ActorLogging with FSM[VoiceConfState, VoiceConfData] with SystemConfiguration {
+
+}
+
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java
index dcfc6274f1748b35762352491d9f00efc7e04034..f8eaf52bc8fcac6b49c863b5d0e29b03509038a4 100755
--- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java
@@ -114,10 +114,7 @@ public class FreeswitchApplication {
     return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
   }
 
-  public void startRecording(String voiceConfId, String meetingid) {
-    String RECORD_DIR = "/var/freeswitch/meetings";
-    String voicePath = RECORD_DIR + File.separatorChar + meetingid + "-" + genTimestamp() + ".wav";
-
+  public void startRecording(String voiceConfId, String meetingid, String voicePath) {
     RecordConferenceCommand rcc = new RecordConferenceCommand(voiceConfId, USER, true, voicePath);
     queueMessage(rcc);
   }
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
index 67e34b23df667c18baf7c7ec8762672364f6524f..7e69fdbdc10b237694bd5cee21227a172db5c767 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
@@ -149,7 +149,7 @@ trait RxJsonMsgDeserializer {
     for {
       m <- deserialize(jsonNode)
     } yield {
-      fsApp.startRecording(m.body.voiceConf, m.body.meetingId)
+      fsApp.startRecording(m.body.voiceConf, m.body.meetingId, m.body.stream)
     }
   }
 
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
index 9521dad5fde810a94a331e0ed1df8d463f038266..69565b9eed6e01f3f965e3e30594c5f543a14d09 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
@@ -191,7 +191,7 @@ case class MeetingMutedEvtMsgBody(muted: Boolean, mutedBy: String)
   object StartRecordingVoiceConfSysMsg { val NAME = "StartRecordingVoiceConfSysMsg" }
   case class StartRecordingVoiceConfSysMsg(header: BbbCoreHeaderWithMeetingId,
                                         body: StartRecordingVoiceConfSysMsgBody) extends BbbCoreMsg
-  case class StartRecordingVoiceConfSysMsgBody(voiceConf: String, meetingId: String)
+  case class StartRecordingVoiceConfSysMsgBody(voiceConf: String, meetingId: String, stream: String)
 
 /**
   * Sent to FS to stop recording voice conference.