- generate recording path in akka-apps for audio
This commit is contained in:
parent
aafcae9d79
commit
c14a946041
@ -82,4 +82,8 @@ services {
|
||||
|
||||
apps {
|
||||
checkPermissions = true
|
||||
}
|
||||
|
||||
voiceConf {
|
||||
recordPath = "/var/freeswitch/meetings"
|
||||
}
|
@ -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")
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 =>
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user