From 4fc0d3bff2f0f3791f840675f495a83d201905f9 Mon Sep 17 00:00:00 2001
From: lxmou666 <772765102@qq.com>
Date: Thu, 7 Jan 2021 00:25:33 +0800
Subject: [PATCH] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E5=AE=8C=E7=BB=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
JianGongYun/TRTC/LiveClassroom.cs | 150 ++++++++++++--------
JianGongYun/TRTC/Windows/LiveWindow.xaml.cs | 10 +-
2 files changed, 101 insertions(+), 59 deletions(-)
diff --git a/JianGongYun/TRTC/LiveClassroom.cs b/JianGongYun/TRTC/LiveClassroom.cs
index 6b610de..0bcc90d 100644
--- a/JianGongYun/TRTC/LiveClassroom.cs
+++ b/JianGongYun/TRTC/LiveClassroom.cs
@@ -19,6 +19,7 @@ using System.Windows.Data;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using AduSkin.Controls.Metro;
namespace JianGongYun.TRTC
{
@@ -122,6 +123,37 @@ namespace JianGongYun.TRTC
}
private static string _RecoderDir;
+
+ ///
+ /// 音频录制文件
+ ///
+ public static string AudioTempPath
+ {
+ get
+ {
+ return Path.Combine(RecoderDir, $"temp_audio.aac");
+ }
+ }
+ ///
+ /// 视频录制文件
+ ///
+ public static string VideoTempPath
+ {
+ get
+ {
+ return Path.Combine(RecoderDir, $"temp_video.avi");
+ }
+ }
+ ///
+ /// 合并后的文件
+ ///
+ public static string ResultFilePath
+ {
+ get
+ {
+ return Path.Combine(RecoderDir, $"result.avi");
+ }
+ }
///
/// 录制内容的具体路径
///
@@ -272,6 +304,7 @@ namespace JianGongYun.TRTC
StartRecordAudio();
}
}
+
///
/// 录音
///
@@ -280,7 +313,7 @@ namespace JianGongYun.TRTC
if (liveWinMode.IsLive && !liveWinMode.AudioRecordRunning)
{
liveWinMode.AudioRecordRunning = true;
- var pars = new TRTCAudioRecordingParams { filePath = Path.Combine(RecoderDir, $"temp_audio.aac") };
+ var pars = new TRTCAudioRecordingParams { filePath = AudioTempPath };
lTRTCCloud.startAudioRecording(ref pars);
}
}
@@ -325,7 +358,6 @@ namespace JianGongYun.TRTC
BackgroundFrame = new Mat(int.Parse(resolution[2]), int.Parse(resolution[1]), MatType.CV_8UC4, backColor);//合成双路视频的背景
var delay = 1000 / (int)fps;//每帧时间
var _recoderDir = RecoderDir;
- var videoFile = Path.Combine(_recoderDir, $"temp_video.avi");
//var videoFrameTemp = Path.Combine(_recoderDir, $"videoFrameTemp.bmp");
var backHeight = BackgroundFrame.Rows;//画面高度
var backWidth = BackgroundFrame.Cols;//画面宽度
@@ -336,17 +368,17 @@ namespace JianGongYun.TRTC
ConcurrentQueue mats = new ConcurrentQueue();
- //int runFps = 0;//实时帧
- //Timer timer = new Timer((a) =>
- //{
- // Debug.Print($"runFps {runFps}. leavingsMat {mats.Count}.");
- // Interlocked.Exchange(ref runFps, 0);
- //}, null, 0, 1000);
+ int runFps = 0;//实时帧
+ Timer timer = new Timer((a) =>
+ {
+ Debug.Print($"runFps {runFps}. leavingsMat {mats.Count}.");
+ Interlocked.Exchange(ref runFps, 0);
+ }, null, 0, 1000);
onEnd = () =>
{
end = true;
- //timer.Dispose();
+ timer.Dispose();
};
//帧合并线程
@@ -422,7 +454,7 @@ namespace JianGongYun.TRTC
}
}
- Skip1:
+ Skip1:
if (liveWinMode.CameraRunning)//摄像头分享中
{
@@ -450,34 +482,35 @@ namespace JianGongYun.TRTC
}
}
- Skip2:
+ Skip2:
mats.Enqueue(BackgroundFrame.CvtColor(ColorConversionCodes.BGRA2BGR));
- //Interlocked.Increment(ref runFps);
+ Interlocked.Increment(ref runFps);
stopwatch.Stop();
- var sleep = delay - (int)stopwatch.ElapsedMilliseconds;//每帧时间减去每帧处理时间为sleep时间
- //if (sleep < 0)//如果处理时间超过了每帧时间,记录下来
- //{
- // delayEqualize += sleep;
- //}
- //if (delayEqualize < 0 && sleep > 0)
- //{
- // delayEqualize += sleep;
- // if (delayEqualize > 0)
- // {
- // delayEqualize = 0;
- // }
- //}
- //var lastsleep = sleep + delayEqualize;//理论休眠时间再去掉补偿时间
- //Debug.Print($"video frame run {stopwatch.ElapsedMilliseconds}. lastsleep {lastsleep}. sum {(stopwatch.ElapsedMilliseconds + lastsleep)}");
- //if (lastsleep > 0)
- //{
- // Thread.Sleep(lastsleep);
- //}
- if (liveWinMode.IsLive && sleep > 0)
+ var sleep = delay - (int)stopwatch.ElapsedMilliseconds - 1;//每帧时间减去每帧处理时间为sleep时间//视频实际时长偏短,再减1是微调
+ if (sleep > 0)
{
- Thread.Sleep(sleep);
+ if (delayEqualize == 0)
+ {
+ Thread.Sleep(sleep);
+ continue;
+ }
+ else
+ {
+ delayEqualize += sleep;
+ if (delayEqualize > 0)
+ {
+ Thread.Sleep(delayEqualize);
+ delayEqualize = 0;
+ continue;
+ }
+ }
}
+ else if (sleep < 0)//如果处理时间超过了每帧时间,记录下来
+ {
+ delayEqualize += sleep;
+ }
+ //Debug.Print($"video frame run {stopwatch.ElapsedMilliseconds}. sleep{sleep}. delayEqualize {delayEqualize}. delay {delay}.");
}
BackgroundFrame?.Dispose();
BackgroundFrame = null;
@@ -487,9 +520,8 @@ namespace JianGongYun.TRTC
//新开线程写文件,减少帧处理时间
Task.Factory.StartNew(() =>
{
- var delayEqualize = 0;//每帧时间补偿,在性能和其他因素影响下delay的时间不一定充足
- VideoWriter vw = new VideoWriter(videoFile, FourCC.H264, fps, BackgroundFrame.Size());
- Stopwatch stopwatch = new Stopwatch();//计时器
+ VideoWriter vw = new VideoWriter(VideoTempPath, FourCC.H264, fps, BackgroundFrame.Size());
+ //Stopwatch stopwatch = new Stopwatch();//计时器
Debug.Print("开始写入视频线程");
while (!end || mats.Count > 0)
{
@@ -497,29 +529,11 @@ namespace JianGongYun.TRTC
{
if (mats.TryDequeue(out var frame))
{
- stopwatch.Restart();
+ //stopwatch.Restart();
vw.Write(frame);
frame.Dispose();
- stopwatch.Stop();
- Debug.Print($"video frame write {stopwatch.ElapsedMilliseconds}");
- //var sleep = delay - (int)stopwatch.ElapsedMilliseconds;//每帧时间减去每帧处理时间为sleep时间
- //if (sleep < 0)//如果处理时间超过了每帧时间,记录下来
- //{
- // delayEqualize += sleep;
- //}
- //if (delayEqualize < 0 && sleep > 0)
- //{
- // delayEqualize += sleep;
- // if (delayEqualize > 0)
- // {
- // delayEqualize = 0;
- // }
- //}
- //var lastsleep = sleep + delayEqualize;//理论休眠时间再去掉补偿时间
- //if (lastsleep > 0)
- //{
- // Thread.Sleep(lastsleep);
- //}
+ //stopwatch.Stop();
+ //Debug.Print($"video frame write {stopwatch.ElapsedMilliseconds}");
}
else
{
@@ -532,6 +546,28 @@ namespace JianGongYun.TRTC
}
}
vw.Dispose();
+ //合并视频
+ var arguments = $@"-i ""{VideoTempPath}"" -i ""{AudioTempPath}"" -c:v copy -c:a copy -strict experimental -y ""{ResultFilePath}""";
+ Process prc = new Process { StartInfo = new ProcessStartInfo { FileName = Path.Combine(Environment.CurrentDirectory, "ffmpeg.exe"), Arguments = arguments, CreateNoWindow = true, UseShellExecute = false } };
+ prc.Start();
+ prc.WaitForExit();
+ if (File.Exists(VideoTempPath))
+ {
+ File.Delete(VideoTempPath);
+ }
+ if (File.Exists(AudioTempPath))
+ {
+ File.Delete(AudioTempPath);
+ }
+ CurrentLiveWindow.Dispatcher.Invoke(new Action(() =>
+ {
+ NoticeManager.NotifiactionShow.AddNotifiaction(new NotifiactionModel()
+ {
+ Title = "提醒",
+ Content = $"成功保存直播视频,路径:{ResultFilePath}。",
+ NotifiactionType = AduSkin.Controls.EnumPromptType.Success
+ });
+ }));
Debug.Print("结束写入视频线程");
}, TaskCreationOptions.LongRunning);
diff --git a/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs b/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs
index 032a938..5066cfb 100644
--- a/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs
+++ b/JianGongYun/TRTC/Windows/LiveWindow.xaml.cs
@@ -52,14 +52,20 @@ namespace JianGongYun.TRTC.Windows
Rad2.Foreground = color;
Rad3.Foreground = color;
Rad4.Foreground = color;
- LiveClassroom.PauseAllView(false);//切前台启动实时预览渲染
+ if (LiveWindowViewModel.IsLive)
+ {
+ LiveClassroom.PauseAllView(false);//切前台启动实时预览渲染
+ }
}
protected override void OnDeactivated(EventArgs e)
{
base.OnDeactivated(e);
- LiveClassroom.PauseAllView(true);//切后台停止实时预览渲染
+ if (LiveWindowViewModel.IsLive)
+ {
+ LiveClassroom.PauseAllView(true);//切后台停止实时预览渲染
+ }
}
private Window settingWindow;