直播完结

This commit is contained in:
lxmou666 2021-01-07 00:25:33 +08:00
parent fb28b4cc89
commit 4fc0d3bff2
2 changed files with 101 additions and 59 deletions

View File

@ -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;
/// <summary>
/// 音频录制文件
/// </summary>
public static string AudioTempPath
{
get
{
return Path.Combine(RecoderDir, $"temp_audio.aac");
}
}
/// <summary>
/// 视频录制文件
/// </summary>
public static string VideoTempPath
{
get
{
return Path.Combine(RecoderDir, $"temp_video.avi");
}
}
/// <summary>
/// 合并后的文件
/// </summary>
public static string ResultFilePath
{
get
{
return Path.Combine(RecoderDir, $"result.avi");
}
}
/// <summary>
/// 录制内容的具体路径
/// </summary>
@ -272,6 +304,7 @@ namespace JianGongYun.TRTC
StartRecordAudio();
}
}
/// <summary>
/// 录音
/// </summary>
@ -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<Mat> mats = new ConcurrentQueue<Mat>();
//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();
};
//帧合并线程
@ -453,31 +485,32 @@ namespace JianGongYun.TRTC
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)
{
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);

View File

@ -52,15 +52,21 @@ namespace JianGongYun.TRTC.Windows
Rad2.Foreground = color;
Rad3.Foreground = color;
Rad4.Foreground = color;
if (LiveWindowViewModel.IsLive)
{
LiveClassroom.PauseAllView(false);//切前台启动实时预览渲染
}
}
protected override void OnDeactivated(EventArgs e)
{
base.OnDeactivated(e);
if (LiveWindowViewModel.IsLive)
{
LiveClassroom.PauseAllView(true);//切后台停止实时预览渲染
}
}
private Window settingWindow;
//设置按钮