[*] 修复通道删除
This commit is contained in:
@@ -363,50 +363,48 @@ public final class Taoyao implements ITaoyao {
|
|||||||
short messageLength = 0;
|
short messageLength = 0;
|
||||||
final byte[] bytes = new byte[1024];
|
final byte[] bytes = new byte[1024];
|
||||||
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
|
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
|
||||||
while (!this.close && this.connect) {
|
try {
|
||||||
try {
|
while (!this.close && this.connect && (length = this.input.read(bytes)) >= 0) {
|
||||||
while (!this.close && (length = this.input.read(bytes)) >= 0) {
|
buffer.put(bytes, 0, length);
|
||||||
buffer.put(bytes, 0, length);
|
while (buffer.position() > 0) {
|
||||||
while (buffer.position() > 0) {
|
if (messageLength <= 0) {
|
||||||
if (messageLength <= 0) {
|
if (buffer.position() < Short.BYTES) {
|
||||||
if (buffer.position() < Short.BYTES) {
|
// 不够消息长度
|
||||||
// 不够消息长度
|
break;
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
buffer.flip();
|
|
||||||
messageLength = buffer.getShort();
|
|
||||||
buffer.compact();
|
|
||||||
if (messageLength > 16 * 1024) {
|
|
||||||
throw new RuntimeException("超过最大数据大小:" + messageLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (buffer.position() < messageLength) {
|
buffer.flip();
|
||||||
// 不够消息长度
|
messageLength = buffer.getShort();
|
||||||
break;
|
buffer.compact();
|
||||||
} else {
|
if (messageLength > 16 * 1024) {
|
||||||
final byte[] message = new byte[messageLength];
|
throw new RuntimeException("超过最大数据大小:" + messageLength);
|
||||||
messageLength = 0;
|
}
|
||||||
buffer.flip();
|
}
|
||||||
buffer.get(message);
|
} else {
|
||||||
buffer.compact();
|
if (buffer.position() < messageLength) {
|
||||||
final String content = new String(this.decrypt.doFinal(message));
|
// 不够消息长度
|
||||||
try {
|
break;
|
||||||
this.on(content);
|
} else {
|
||||||
} catch (Exception e) {
|
final byte[] message = new byte[messageLength];
|
||||||
Log.e(Taoyao.class.getSimpleName(), "处理信令异常:" + content, e);
|
messageLength = 0;
|
||||||
this.taoyaoListener.onError(e);
|
buffer.flip();
|
||||||
}
|
buffer.get(message);
|
||||||
|
buffer.compact();
|
||||||
|
final String content = new String(this.decrypt.doFinal(message));
|
||||||
|
try {
|
||||||
|
this.on(content);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(Taoyao.class.getSimpleName(), "处理信令异常:" + content, e);
|
||||||
|
this.taoyaoListener.onError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(Taoyao.class.getSimpleName(), "接收信令异常", e);
|
|
||||||
this.disconnect();
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(Taoyao.class.getSimpleName(), "接收信令异常", e);
|
||||||
|
this.disconnect();
|
||||||
}
|
}
|
||||||
if (!this.close && !this.connect) {
|
if (!this.close) {
|
||||||
this.messageHandler.post(this::connect);
|
this.messageHandler.post(this::connect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,7 +437,11 @@ public final class Taoyao implements ITaoyao {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void push(Message message) {
|
public void push(Message message) {
|
||||||
if (this.output == null) {
|
if (this.close) {
|
||||||
|
Log.w(Taoyao.class.getSimpleName(), "通道已经关闭:" + message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.connect) {
|
||||||
Log.w(Taoyao.class.getSimpleName(), "通道没有打开:" + message);
|
Log.w(Taoyao.class.getSimpleName(), "通道没有打开:" + message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -448,6 +450,7 @@ public final class Taoyao implements ITaoyao {
|
|||||||
this.output.write(this.encrypt(message));
|
this.output.write(this.encrypt(message));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(Taoyao.class.getSimpleName(), "请求信令异常:" + message, e);
|
Log.e(Taoyao.class.getSimpleName(), "请求信令异常:" + message, e);
|
||||||
|
this.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -792,13 +792,15 @@ class Taoyao {
|
|||||||
const { roomId, clientId, host, audioPort, videoPort, rtpCapabilities, audioStreamId, videoStreamId, audioProducerId, videoProducerId } = body;
|
const { roomId, clientId, host, audioPort, videoPort, rtpCapabilities, audioStreamId, videoStreamId, audioProducerId, videoProducerId } = body;
|
||||||
const plainTransportOptions = {
|
const plainTransportOptions = {
|
||||||
...config.mediasoup.plainTransportOptions,
|
...config.mediasoup.plainTransportOptions,
|
||||||
rtcpMux : true,
|
rtcpMux: false,
|
||||||
comedia : true
|
comedia: false
|
||||||
};
|
};
|
||||||
let videoConsumerId;
|
let videoConsumerId;
|
||||||
let audioConsumerId;
|
let audioConsumerId;
|
||||||
let audioTransportId;
|
let audioTransportId;
|
||||||
let videoTransportId;
|
let videoTransportId;
|
||||||
|
let audioRtpParameters;
|
||||||
|
let videoRtpParameters;
|
||||||
if(audioProducerId) {
|
if(audioProducerId) {
|
||||||
const audioTransport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions);
|
const audioTransport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions);
|
||||||
audioTransportId = audioTransport.id;
|
audioTransportId = audioTransport.id;
|
||||||
@@ -810,9 +812,9 @@ class Taoyao {
|
|||||||
room.transports.delete(audioTransport.id)
|
room.transports.delete(audioTransport.id)
|
||||||
});
|
});
|
||||||
await audioTransport.connect({
|
await audioTransport.connect({
|
||||||
ip : host,
|
ip : host,
|
||||||
port : audioPort,
|
port : audioPort,
|
||||||
rtcpPort : audioPort
|
rtcpPort: audioPort
|
||||||
});
|
});
|
||||||
const audioConsumer = await audioTransport.consume({
|
const audioConsumer = await audioTransport.consume({
|
||||||
producerId: audioProducerId,
|
producerId: audioProducerId,
|
||||||
@@ -820,6 +822,7 @@ class Taoyao {
|
|||||||
paused: true
|
paused: true
|
||||||
});
|
});
|
||||||
audioConsumerId = audioConsumer.id;
|
audioConsumerId = audioConsumer.id;
|
||||||
|
audioRtpParameters = audioConsumer.rtpParameters;
|
||||||
await audioConsumer.resume();
|
await audioConsumer.resume();
|
||||||
audioConsumer.clientId = clientId;
|
audioConsumer.clientId = clientId;
|
||||||
audioConsumer.streamId = audioStreamId;
|
audioConsumer.streamId = audioStreamId;
|
||||||
@@ -828,7 +831,7 @@ class Taoyao {
|
|||||||
console.log("controlServerRecord audioConsumer close:", audioConsumer.id);
|
console.log("controlServerRecord audioConsumer close:", audioConsumer.id);
|
||||||
room.consumers.delete(audioConsumer.id);
|
room.consumers.delete(audioConsumer.id);
|
||||||
});
|
});
|
||||||
console.log("controlServerRecord audio", audioTransportId, audioConsumerId, audioTransport.tuple);
|
console.log("controlServerRecord audio", audioTransportId, audioConsumerId, audioTransport.tuple, audioRtpParameters);
|
||||||
}
|
}
|
||||||
if(videoProducerId) {
|
if(videoProducerId) {
|
||||||
const videoTransport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions);
|
const videoTransport = await room.mediasoupRouter.createPlainTransport(plainTransportOptions);
|
||||||
@@ -841,9 +844,9 @@ class Taoyao {
|
|||||||
room.transports.delete(videoTransport.id)
|
room.transports.delete(videoTransport.id)
|
||||||
});
|
});
|
||||||
await videoTransport.connect({
|
await videoTransport.connect({
|
||||||
ip : host,
|
ip : host,
|
||||||
port : videoPort,
|
port : videoPort,
|
||||||
rtcpPort : videoPort
|
rtcpPort: videoPort
|
||||||
});
|
});
|
||||||
const videoConsumer = await videoTransport.consume({
|
const videoConsumer = await videoTransport.consume({
|
||||||
producerId: videoProducerId,
|
producerId: videoProducerId,
|
||||||
@@ -851,6 +854,7 @@ class Taoyao {
|
|||||||
paused: true
|
paused: true
|
||||||
});
|
});
|
||||||
videoConsumerId = videoConsumer.id;
|
videoConsumerId = videoConsumer.id;
|
||||||
|
videoRtpParameters = videoConsumer.rtpParameters;
|
||||||
await videoConsumer.resume();
|
await videoConsumer.resume();
|
||||||
videoConsumer.clientId = clientId;
|
videoConsumer.clientId = clientId;
|
||||||
videoConsumer.streamId = videoStreamId;
|
videoConsumer.streamId = videoStreamId;
|
||||||
@@ -859,14 +863,16 @@ class Taoyao {
|
|||||||
console.log("controlServerRecord videoConsumer close:", videoConsumer.id);
|
console.log("controlServerRecord videoConsumer close:", videoConsumer.id);
|
||||||
room.consumers.delete(videoConsumer.id);
|
room.consumers.delete(videoConsumer.id);
|
||||||
});
|
});
|
||||||
console.log("controlServerRecord video:", videoTransportId, videoConsumerId, videoTransport.tuple);
|
console.log("controlServerRecord video:", videoTransportId, videoConsumerId, videoTransport.tuple, videoRtpParameters);
|
||||||
}
|
}
|
||||||
message.body = {
|
message.body = {
|
||||||
roomId : roomId,
|
roomId : roomId,
|
||||||
audioConsumerId : audioConsumerId,
|
audioConsumerId : audioConsumerId,
|
||||||
videoConsumerId : videoConsumerId,
|
videoConsumerId : videoConsumerId,
|
||||||
audioTransportId : audioTransportId,
|
audioTransportId : audioTransportId,
|
||||||
videoTransportId : videoTransportId,
|
videoTransportId : videoTransportId,
|
||||||
|
audioRtpParameters: audioRtpParameters,
|
||||||
|
videoRtpParameters: videoRtpParameters,
|
||||||
};
|
};
|
||||||
me.push(message);
|
me.push(message);
|
||||||
}
|
}
|
||||||
@@ -1528,6 +1534,11 @@ class Taoyao {
|
|||||||
*/
|
*/
|
||||||
transportEvent(type, roomId, transport) {
|
transportEvent(type, roomId, transport) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
const room = self.rooms.get(roomId);
|
||||||
|
if(!room) {
|
||||||
|
// TODO:提示
|
||||||
|
return;
|
||||||
|
}
|
||||||
/********************* 通用通道事件 *********************/
|
/********************* 通用通道事件 *********************/
|
||||||
transport.on("routerclose", () => {
|
transport.on("routerclose", () => {
|
||||||
console.info("transport routerclose:", transport.id);
|
console.info("transport routerclose:", transport.id);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
<el-button @click="taoyao.mediaProducerResume(videoProducer.id)" v-show="videoProducer && videoProducer.paused" type="danger" title="打开摄像头" :icon="VideoPlay" circle />
|
<el-button @click="taoyao.mediaProducerResume(videoProducer.id)" v-show="videoProducer && videoProducer.paused" type="danger" title="打开摄像头" :icon="VideoPlay" circle />
|
||||||
<el-button @click="taoyao.mediaProducerPause(videoProducer.id)" v-show="videoProducer && !videoProducer.paused" type="primary" title="关闭摄像头" :icon="VideoPause" circle />
|
<el-button @click="taoyao.mediaProducerPause(videoProducer.id)" v-show="videoProducer && !videoProducer.paused" type="primary" title="关闭摄像头" :icon="VideoPause" circle />
|
||||||
<el-button @click="exchangeVideoSource" :icon="Refresh" circle title="交换媒体" />
|
<el-button @click="exchangeVideoSource" :icon="Refresh" circle title="交换媒体" />
|
||||||
<el-button @onclick="localPhotograph" :icon="Camera" circle title="拍照" />
|
<el-button @click="localPhotograph" :icon="Camera" circle title="拍照" />
|
||||||
<el-button @onclick="localClientRecord" :icon="VideoCamera" circle title="录像" :type="clientRecord ? 'danger' : ''" />
|
<el-button @click="localClientRecord" :icon="VideoCamera" circle title="录像" :type="clientRecord ? 'danger' : ''" />
|
||||||
<el-button @click="taoyao.controlServerRecord(client.clientId, (serverRecord = !serverRecord))" :icon="MostlyCloudy" circle title="录像" :type="serverRecord ? 'danger' : ''" />
|
<el-button @click="taoyao.controlServerRecord(client.clientId, (serverRecord = !serverRecord))" :icon="MostlyCloudy" circle title="录像" :type="serverRecord ? 'danger' : ''" />
|
||||||
<el-button @click="taoyao.mediaProducerStatus()" :icon="InfoFilled" circle title="媒体信息" />
|
<el-button @click="taoyao.mediaProducerStatus()" :icon="InfoFilled" circle title="媒体信息" />
|
||||||
<el-popover placement="top" :width="240" trigger="hover">
|
<el-popover placement="top" :width="240" trigger="hover">
|
||||||
|
|||||||
@@ -1958,7 +1958,7 @@ class Taoyao extends RemoteClient {
|
|||||||
let track;
|
let track;
|
||||||
try {
|
try {
|
||||||
console.debug("打开麦克风");
|
console.debug("打开麦克风");
|
||||||
let track = self.getAudioTrack();
|
let track = await self.getAudioTrack();
|
||||||
this.audioProducer = await this.sendTransport.produce({
|
this.audioProducer = await this.sendTransport.produce({
|
||||||
track,
|
track,
|
||||||
codecOptions: {
|
codecOptions: {
|
||||||
@@ -2528,7 +2528,7 @@ class Taoyao extends RemoteClient {
|
|||||||
videoBitsPerSecond: 2400 * 1000,
|
videoBitsPerSecond: 2400 * 1000,
|
||||||
mimeType: 'video/webm;codecs=opus,h264',
|
mimeType: 'video/webm;codecs=opus,h264',
|
||||||
});
|
});
|
||||||
mediaRecorder.onstop = function (e) {
|
me.mediaRecorder.onstop = function (e) {
|
||||||
const blob = new Blob(me.mediaRecorderChunks);
|
const blob = new Blob(me.mediaRecorderChunks);
|
||||||
const objectURL = URL.createObjectURL(blob);
|
const objectURL = URL.createObjectURL(blob);
|
||||||
const download = document.createElement('a');
|
const download = document.createElement('a');
|
||||||
@@ -2541,7 +2541,7 @@ class Taoyao extends RemoteClient {
|
|||||||
URL.revokeObjectURL(objectURL);
|
URL.revokeObjectURL(objectURL);
|
||||||
me.mediaRecorderChunks = [];
|
me.mediaRecorderChunks = [];
|
||||||
};
|
};
|
||||||
mediaRecorder.ondataavailable = (e) => {
|
me.mediaRecorder.ondataavailable = (e) => {
|
||||||
me.mediaRecorderChunks.push(e.data);
|
me.mediaRecorderChunks.push(e.data);
|
||||||
};
|
};
|
||||||
me.mediaRecorder.start();
|
me.mediaRecorder.start();
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ public class FfmpegProperties {
|
|||||||
private String storageImagePath;
|
private String storageImagePath;
|
||||||
@Schema(title = "视频存储目录", description = "视频存储目录")
|
@Schema(title = "视频存储目录", description = "视频存储目录")
|
||||||
private String storageVideoPath;
|
private String storageVideoPath;
|
||||||
|
@Schema(title = "预览截图时间", description = "预览截图时间")
|
||||||
|
private Integer previewTime;
|
||||||
|
@Schema(title = "预览截图时间", description = "预览截图时间")
|
||||||
|
private String durationRegex;
|
||||||
@Schema(title = "录像录像地址", description = "录像录像地址")
|
@Schema(title = "录像录像地址", description = "录像录像地址")
|
||||||
private String host;
|
private String host;
|
||||||
@Schema(title = "录像最小端口", description = "录像最小端口")
|
@Schema(title = "录像最小端口", description = "录像最小端口")
|
||||||
|
|||||||
@@ -235,13 +235,12 @@ taoyao:
|
|||||||
c=IN IP4 127.0.0.1
|
c=IN IP4 127.0.0.1
|
||||||
a=rtpmap:100 OPUS/48000/2
|
a=rtpmap:100 OPUS/48000/2
|
||||||
a=fmtp:100 sprop-stereo=1
|
a=fmtp:100 sprop-stereo=1
|
||||||
m=video %d RTP/AVP 107
|
m=video %d RTP/AVP 101
|
||||||
c=IN IP4 127.0.0.1
|
c=IN IP4 127.0.0.1
|
||||||
a=rtpmap:107 H264/90000
|
a=rtpmap:101 VP8/90000
|
||||||
a=fmtp:107 packetization-mode=1
|
|
||||||
# 录像命令
|
# 录像命令
|
||||||
record: ffmpeg -protocol_whitelist "file,rtp,udp" -y -i %s %s
|
record: ffmpeg -protocol_whitelist "file,rtp,udp" -y -i %s %s
|
||||||
# 截图命令
|
# 预览命令
|
||||||
preview: ffmpeg -y -i %s -ss %d -vframes 1 -f image2 %s
|
preview: ffmpeg -y -i %s -ss %d -vframes 1 -f image2 %s
|
||||||
# 时长命令
|
# 时长命令
|
||||||
duration: ffprobe -i %s -show_entries format=duration
|
duration: ffprobe -i %s -show_entries format=duration
|
||||||
@@ -251,6 +250,10 @@ taoyao:
|
|||||||
storage-image-path: /data/taoyao/storage/image
|
storage-image-path: /data/taoyao/storage/image
|
||||||
# 视频存储目录
|
# 视频存储目录
|
||||||
storage-video-path: /data/taoyao/storage/video
|
storage-video-path: /data/taoyao/storage/video
|
||||||
|
# 预览时间
|
||||||
|
preview-time: 4
|
||||||
|
# 时长提取
|
||||||
|
duration-regex: .*duration\=([0-9\.]+).*
|
||||||
# 录像地址
|
# 录像地址
|
||||||
#host: 127.0.0.1
|
#host: 127.0.0.1
|
||||||
host: 192.168.8.40
|
host: 192.168.8.40
|
||||||
|
|||||||
@@ -16,29 +16,28 @@ public class RecorderTest {
|
|||||||
ffmpegProperties.setHost("127.0.0.1");
|
ffmpegProperties.setHost("127.0.0.1");
|
||||||
ffmpegProperties.setSdp("""
|
ffmpegProperties.setSdp("""
|
||||||
v=0
|
v=0
|
||||||
o=- 0 0 IN IP4 %s
|
o=- 0 0 IN IP4 127.0.0.1
|
||||||
s=TaoyaoRecord
|
s=TaoyaoRecord
|
||||||
t=0 0
|
t=0 0
|
||||||
m=audio %d RTP/AVP 97
|
m=audio %d RTP/AVP 97
|
||||||
c=IN IP4 %s
|
c=IN IP4 127.0.0.1
|
||||||
a=rtpmap:97 OPUS/48000/2
|
a=rtpmap:97 OPUS/48000/2
|
||||||
a=fmtp:97 sprop-stereo=1
|
a=fmtp:97 sprop-stereo=1
|
||||||
m=video %d RTP/AVP 96
|
m=video %d RTP/AVP 96
|
||||||
c=IN IP4 %s
|
c=IN IP4 127.0.0.1
|
||||||
a=rtpmap:96 VP8/90000
|
a=rtpmap:96 VP8/90000
|
||||||
a=fmtp:96 packetization-mode=1
|
|
||||||
""");
|
""");
|
||||||
// ffmpegProperties.setSdp("""
|
// ffmpegProperties.setSdp("""
|
||||||
// v=0
|
// v=0
|
||||||
// o=- 0 0 IN IP4 %s
|
// o=- 0 0 IN IP4 127.0.0.1
|
||||||
// s=TaoyaoRecord
|
// s=TaoyaoRecord
|
||||||
// t=0 0
|
// t=0 0
|
||||||
// m=audio %d RTP/AVP 97
|
// m=audio %d RTP/AVP 97
|
||||||
// c=IN IP4 %s
|
// c=IN IP4 127.0.0.1
|
||||||
// a=rtpmap:97 OPUS/48000/2
|
// a=rtpmap:97 OPUS/48000/2
|
||||||
// a=fmtp:97 sprop-stereo=1
|
// a=fmtp:97 sprop-stereo=1
|
||||||
// m=video %d RTP/AVP 96
|
// m=video %d RTP/AVP 96
|
||||||
// c=IN IP4 %s
|
// c=IN IP4 127.0.0.1
|
||||||
// a=rtpmap:96 H264/90000
|
// a=rtpmap:96 H264/90000
|
||||||
// a=fmtp:96 packetization-mode=1
|
// a=fmtp:96 packetization-mode=1
|
||||||
// """);
|
// """);
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ public class Recorder {
|
|||||||
this.thread.setDaemon(true);
|
this.thread.setDaemon(true);
|
||||||
this.thread.setName("TaoyaoRecord");
|
this.thread.setName("TaoyaoRecord");
|
||||||
this.thread.start();
|
this.thread.start();
|
||||||
|
log.info("开始录像:{}", this.folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,14 +211,14 @@ public class Recorder {
|
|||||||
* 视频预览截图
|
* 视频预览截图
|
||||||
*/
|
*/
|
||||||
private void preview() {
|
private void preview() {
|
||||||
int time = 2;
|
int time = this.ffmpegProperties.getPreviewTime();
|
||||||
final File file = Paths.get(this.preview).toFile();
|
final File file = Paths.get(this.preview).toFile();
|
||||||
while(time > 0 && !(file.exists() && file.length() > 0L)) {
|
do {
|
||||||
log.debug("视频预览截图:{}", this.preview);
|
log.debug("视频预览:{}", this.preview);
|
||||||
final String previewScript = String.format(this.ffmpegProperties.getPreview(), this.filepath, time, this.preview);
|
final String previewScript = String.format(this.ffmpegProperties.getPreview(), this.filepath, time, this.preview);
|
||||||
ScriptUtils.execute(previewScript);
|
ScriptUtils.execute(previewScript);
|
||||||
time /= 2;
|
time /= 2;
|
||||||
}
|
} while (time > 0 && !(file.exists() && file.length() > 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,7 +228,7 @@ public class Recorder {
|
|||||||
log.debug("视频时长:{}", this.filepath);
|
log.debug("视频时长:{}", this.filepath);
|
||||||
final String durationScript = String.format(this.ffmpegProperties.getDuration(), this.filepath);
|
final String durationScript = String.format(this.ffmpegProperties.getDuration(), this.filepath);
|
||||||
final ScriptExecutor executor = ScriptUtils.execute(durationScript);
|
final ScriptExecutor executor = ScriptUtils.execute(durationScript);
|
||||||
final Pattern pattern = Pattern.compile(".*duration\\=([0-9\\.]+).*");
|
final Pattern pattern = Pattern.compile(this.ffmpegProperties.getDurationRegex());
|
||||||
final Matcher matcher = pattern.matcher(executor.getResult());
|
final Matcher matcher = pattern.matcher(executor.getResult());
|
||||||
String duration = null;
|
String duration = null;
|
||||||
if(matcher.find()) {
|
if(matcher.find()) {
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ public class ControlServerRecordProtocol extends ProtocolControlAdapter implemen
|
|||||||
message.setBody(body);
|
message.setBody(body);
|
||||||
final Client mediaClient = room.getMediaClient();
|
final Client mediaClient = room.getMediaClient();
|
||||||
mediaClient.request(message);
|
mediaClient.request(message);
|
||||||
|
// TODO:回写ID,格式自动判断
|
||||||
return recorder.getFilepath();
|
return recorder.getFilepath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user