This commit is contained in:
lxmou666 2020-12-28 09:40:37 +08:00
parent de4c763f06
commit db4a481037
21 changed files with 2069 additions and 105 deletions

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net45;net46</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<GenerateDocumentFile>true</GenerateDocumentFile>
<UseWpf>true</UseWpf>
<UseWindowsForms>true</UseWindowsForms>
@ -16,6 +16,8 @@
<PackageReference Include="CommonServiceLocator" Version="2.0.5" />
<PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.1.20201226" />
<PackageReference Include="OpenCvSharp4.WpfExtensions" Version="4.5.1.20201226" />
<PackageReference Include="zlib.net" Version="1.0.4" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
@ -48,6 +50,11 @@
<HintPath>TRTC_SDK\Win32\lib\ManageLiteAV.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="OpenCvSharp4">
<Version>4.5.1.20201226</Version>
</PackageReference>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="set Platform=Win64&#xD;&#xA;SETLOCAL ENABLEDELAYEDEXPANSION&#xD;&#xA;if $(PlatformName)==x86 ( &#xD;&#xA;set Platform=Win32&#xD;&#xA;)&#xD;&#xA;copy /Y &quot;$(ProjectDir)TRTC_SDK\!Platform!\lib\*.dll&quot; &quot;$(ProjectDir)$(OutDir)&quot;&#xD;&#xA;ENDLOCAL" />
</Target>

View File

@ -0,0 +1,8 @@
{
"profiles": {
"JianGongYun": {
"commandName": "Project",
"nativeDebugging": false
}
}
}

View File

@ -7,6 +7,246 @@
<SolidColorBrush x:Key="Item.SelectedActive.foreground" Color="#396cd2" />
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da" />
<!-- ScrollViewer 滚动条 -->
<Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Grid>
<!--滚动条颜色-->
<Border Background="#646465" CornerRadius="3"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HorizontalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Opacity" Value="0.2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="VerticalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Opacity" Value="0.2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Rectangle Fill="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--滚动条上下按钮-->
<Style x:Key="VerticalScrollBarPageButton2" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Opacity" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Rectangle Fill="#90000000" Width="0" Height="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="for_scrollbar" TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="false"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Margin" Value="0,1,1,6"/>
<Setter Property="Width" Value="10"/>
<Setter Property="MinWidth" Value="5"/>
<Setter Property="Opacity" Value="0.2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollBar}">
<Grid x:Name="Bg" SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<RepeatButton Grid.Row="0" Style="{StaticResource VerticalScrollBarPageButton2}" Command="{x:Static ScrollBar.PageUpCommand}"/>
<Track x:Name="PART_Track" Grid.Row="1" IsEnabled="{TemplateBinding IsMouseOver}" IsDirectionReversed="true">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}" Command="{x:Static ScrollBar.PageUpCommand}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource VerticalScrollBarPageButton}" Command="{x:Static ScrollBar.PageDownCommand}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"/>
</Track.Thumb>
</Track>
<RepeatButton Grid.Row="2" Style="{StaticResource VerticalScrollBarPageButton2}" Command="{x:Static ScrollBar.PageDownCommand}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Margin" Value="1,0,6,1"/>
<Setter Property="Height" Value="5"/>
<Setter Property="MinHeight" Value="5"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Opacity" Value="0.2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollBar}">
<Grid x:Name="Bg" SnapsToDevicePixels="true">
<Track x:Name="PART_Track" IsEnabled="{TemplateBinding IsMouseOver}">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageLeftCommand}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource HorizontalScrollBarPageButton}" Command="{x:Static ScrollBar.PageRightCommand}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="for_scrollviewer"
TargetType="{x:Type ScrollViewer}">
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<Grid Background="{TemplateBinding Background}">
<ScrollContentPresenter Cursor="{TemplateBinding Cursor}" Margin="{TemplateBinding Padding}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
<ScrollBar x:Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
Style="{StaticResource for_scrollbar}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Maximum="{TemplateBinding ScrollableWidth}"
Orientation="Horizontal"
Style="{StaticResource for_scrollbar}"
VerticalAlignment="Bottom"
Value="{TemplateBinding HorizontalOffset}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="ScrollChanged" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.8"
Duration="0:0:1"/>
<DoubleAnimation
Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.2"
Duration="0:0:1"
BeginTime="0:0:1"/>
<DoubleAnimation
Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.8"
Duration="0:0:1"/>
<DoubleAnimation
Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.2"
Duration="0:0:1"
BeginTime="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseEnter"
SourceName="PART_VerticalScrollBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.8"
Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave"
SourceName="PART_VerticalScrollBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="PART_VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.2"
Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseEnter"
SourceName="PART_HorizontalScrollBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.8"
Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave"
SourceName="PART_HorizontalScrollBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="PART_HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="0.2"
Duration="0:0:0.7"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--默认ScrollBar-->
<Style TargetType="ScrollBar" BasedOn="{StaticResource for_scrollbar}"/>
<!--默认ScrollView-->
<Style TargetType="ScrollViewer" BasedOn="{StaticResource for_scrollviewer}"/>
<Style x:Key="LeftIndicatorStyle" TargetType="{x:Type Metro:SegmentControl}">
<Setter Property="Padding" Value="0" />
<Setter Property="CornerRadius" Value="0" />
@ -94,7 +334,27 @@
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="Width" Value="100"></Setter>
<Setter Property="Width" Value="125"></Setter>
<Setter Property="TextAlignment" Value="Left"></Setter>
</Style>
<!--图标按钮-->
<Style TargetType="Button" x:Key="CusIconBtn">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="0" BorderBrush="Black">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,16 @@
<UserControl x:Class="JianGongYun.TRTC.Components.CountdownControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:JianGongYun.TRTC.Components" Loaded="UserControl_Loaded"
mc:Ignorable="d">
<UserControl.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="scale" ></ScaleTransform>
</TransformGroup>
</UserControl.RenderTransform>
<Border CornerRadius="100" Background="#dddddd" Width="100" Height="100">
<TextBlock x:Name="tb" Width="100" Height="100" Text="9" FontSize="85" TextAlignment="Center" FontWeight="Bold" FontFamily="FangSong" Foreground="Red"></TextBlock>
</Border>
</UserControl>

View File

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace JianGongYun.TRTC.Components
{
/// <summary>
/// CountdownControl.xaml 的交互逻辑
/// </summary>
public partial class CountdownControl : UserControl
{
private Grid grid = null;
private Window wm;
public CountdownControl(Grid _grid, Window _wm)
{
InitializeComponent();
grid = _grid;
wm = _wm;
}
/// <summary>
/// 创建动画执行对象
/// </summary>
private Storyboard sb = null;
/// <summary>
/// 给文本框赋值
/// </summary>
private string txtValue = string.Empty;
public string TxtValue
{
get { return txtValue; }
set { txtValue = value; this.tb.Text = txtValue; }
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
//创建动画对象实例
sb = new Storyboard();
//ScaleX缩放动画
//DoubleAnimation daX = new DoubleAnimation();
//daX.Duration = TimeSpan.FromSeconds(0.6);
//daX.From = 1.35;
//daX.To = 1;
//Storyboard.SetTarget(daX, this);
//Storyboard.SetTargetProperty(daX, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
////ScaleY缩放动画
//DoubleAnimation daY = new DoubleAnimation();
//daY.Duration = TimeSpan.FromSeconds(0.6);
//daY.From = 1.35;
//daY.To = 1;
//Storyboard.SetTarget(daY, this);
//Storyboard.SetTargetProperty(daY, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
//Opacity变换动画
DoubleAnimation daO = new DoubleAnimation();
daO.Duration = TimeSpan.FromSeconds(0.6);
daO.From = 0;
daO.To = 1;
Storyboard.SetTarget(daO, this);
Storyboard.SetTargetProperty(daO, new PropertyPath("(Opacity)"));
//sb.Children.Add(daX);
//sb.Children.Add(daY);
sb.Children.Add(daO);
DoubleAnimation daTop2 = new DoubleAnimation();
daTop2.BeginTime = TimeSpan.FromSeconds(0.7);
daTop2.Duration = TimeSpan.FromSeconds(0.2);
daTop2.EasingFunction = new BounceEase() { Bounces = 10, EasingMode = EasingMode.EaseInOut };
Storyboard.SetTarget(daTop2, wm);
Storyboard.SetTargetProperty(daTop2, new PropertyPath("(Top)"));
sb.Children.Add(daTop2);
sb.Completed += new EventHandler(sb_Completed);
sb.Begin(this, true);
}
private void sb_Completed(object sender, EventArgs e)
{
//解除绑定
sb.Remove(this);
sb.Children.Clear();
grid.Children.Clear();
}
}
}

View File

@ -1,10 +0,0 @@
<UserControl x:Class="JianGongYun.TRTC.Components.SytemGatherVolumeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:JianGongYun.TRTC.Components"
xmlns:Metro="clr-namespace:AduSkin.Controls.Metro;assembly=AduSkin"
mc:Ignorable="d"
Width="auto">
</UserControl>

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace JianGongYun.TRTC.Components
{
/// <summary>
/// SytemGatherVolumeControl.xaml 的交互逻辑
/// </summary>
public partial class SytemGatherVolumeControl : UserControl
{
public SytemGatherVolumeControl()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,500 @@
using ManageLiteAV;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace JianGongYun.TRTC.Components
{
public class TXLiteAVVideoView : Canvas, IDisposable
{
private bool mOccupy = false; // view 是否已被占用
private bool mLocalView = false; // 是否为本地画面
private bool mPause = false;
private bool mFirstFrame = false;
private string mUserId;
private TRTCVideoStreamType mStreamType;
private TRTCVideoFillMode mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit; // 0填充1适应
private volatile FrameBufferInfo mArgbFrame = new FrameBufferInfo(); // 帧缓存
// 位图缓存防止GC频繁
private WriteableBitmap mWriteableBitmap;
private Int32Rect mInt32Rect;
private Pen mPen;
public TXLiteAVVideoView()
{
mPen = new Pen { Brush = Brushes.DarkGray, Thickness = 1 };
}
/// <summary>
/// 设置 View 绑定参数
/// </summary>
/// <param name="userId">需要渲染画面的 userId如果是本地画面则传空字符串。</param>
/// <param name="type">渲染类型</param>
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
/// <param name="local">渲染本地画面SDK 返回的 userId 为""</param>
/// <returns>true绑定成功false绑定失败</returns>
public bool RegEngine(string userId, TRTCVideoStreamType type, ITRTCCloud engine, bool local = false)
{
if (mOccupy) return false;
mLocalView = local;
mUserId = userId;
mStreamType = type;
int count = TXLiteAVVideoViewManager.GetInstance().Count;
if (engine != null)
{
if (count == 0)
{
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
}
if (!mLocalView)
{
engine.setRemoteVideoRenderCallback(userId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
}
}
if (mLocalView)
TXLiteAVVideoViewManager.GetInstance().AddView("", type, this);
else
TXLiteAVVideoViewManager.GetInstance().AddView(userId, type, this);
lock (mArgbFrame)
ReleaseBuffer(mArgbFrame);
mOccupy = true;
this.InvalidateVisual();
return true;
}
/// <summary>
/// 移除 View 绑定参数
/// </summary>
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
public void RemoveEngine(ITRTCCloud engine)
{
if (mLocalView)
TXLiteAVVideoViewManager.GetInstance().RemoveView("", mStreamType, this);
else
TXLiteAVVideoViewManager.GetInstance().RemoveView(mUserId, mStreamType, this);
int count = TXLiteAVVideoViewManager.GetInstance().Count;
if (engine != null)
{
if (count == 0)
{
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
}
if (!mLocalView && !TXLiteAVVideoViewManager.GetInstance().HasUserId(mUserId))
{
engine.setRemoteVideoRenderCallback(mUserId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
}
}
lock (mArgbFrame)
ReleaseBuffer(mArgbFrame);
mUserId = "";
mOccupy = false;
mLocalView = false;
mFirstFrame = false;
mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit;
this.InvalidateVisual();
}
/// <summary>
/// 设置 View 的渲染模式
/// </summary>
/// <param name="mode">渲染模式</param>
public void SetRenderMode(TRTCVideoFillMode mode)
{
mRenderMode = mode;
}
/// <summary>
/// 判断 View 是否被占用
/// </summary>
/// <returns>true当前 View 已被占用false当前 View 未被占用</returns>
public bool IsViewOccupy()
{
return mOccupy;
}
/// <summary>
/// 暂停渲染,显示默认图片
/// </summary>
/// <param name="pause">是否暂停</param>
public void SetPause(bool pause)
{
if (mPause != pause)
{
mPause = pause;
if (mPause)
{
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x20, 0x20, 0x20));
}
else
{
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0x00, 0x00));
// 避免刷新最后一帧数据
lock (mArgbFrame)
ReleaseBuffer(mArgbFrame);
}
this.InvalidateVisual();
}
}
/// <summary>
/// 清除所有映射信息
/// </summary>
public static void RemoveAllRegEngine()
{
TXLiteAVVideoViewManager.GetInstance().RemoveAllView();
}
public bool AppendVideoFrame(byte[] data, int width, int height, TRTCVideoPixelFormat videoFormat, TRTCVideoRotation rotation)
{
if (!mFirstFrame)
mFirstFrame = true;
if (mPause)
return false;
if (data == null || data.Length <= 0)
return false;
// data 数据有误
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32 && width * height * 4 != data.Length)
return false;
// 暂时不支持其他 YUV 类型
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420 && width * height * 3 / 2 != data.Length)
return false;
// 目前只实现了 BGRA32 的数据类型,如需其他类型请重写,并设置回调的数据类型
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32)
{
lock (mArgbFrame)
{
if (mArgbFrame.data == null || mArgbFrame.width != width || mArgbFrame.height != height)
{
ReleaseBuffer(mArgbFrame);
mArgbFrame.width = width;
mArgbFrame.height = height;
mArgbFrame.data = new byte[data.Length];
}
Buffer.BlockCopy(data, 0, mArgbFrame.data, 0, (int)data.Length);
mArgbFrame.newFrame = true;
mArgbFrame.rotation = rotation;
}
}
// 回到主线程刷新当前画面
this.Dispatcher.Invoke(new Action(() =>
{
this.InvalidateVisual();
}));
return true;
}
protected override void OnRender(DrawingContext dc)
{
bool needDrawFrame = true;
if (mPause)
needDrawFrame = false;
if (mArgbFrame.data == null)
needDrawFrame = false;
if (!needDrawFrame)
{
return;
}
lock (mArgbFrame)
{
if (mArgbFrame.data == null)
return;
if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fill)
{
RenderFillMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
}
else if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fit)
{
RenderFitMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
}
}
}
/// <summary>
/// 渲染回调int width, int height, int rotation,WriteableBitmap image
/// </summary>
public event Action<int, int, int, WriteableBitmap> OnRenderVideoFrameHandler;
private void RenderFillMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
{
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
PixelFormat pixelFormat = PixelFormats.Pbgra32;
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
int stride = bytesPerPixel * width;
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
{
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
mInt32Rect = new Int32Rect(0, 0, width, height);
}
mWriteableBitmap.Lock();
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
mWriteableBitmap.AddDirtyRect(mInt32Rect);
mWriteableBitmap.Unlock();
//var tt = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
//OpenCvSharp.Mat result = OpenCvSharp.Extensions.BitmapConverter.ToMat(tt);
//tt.Dispose();
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, OpenCvSharp.MatType.CV_8UC4, 4);
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, data.Length, 4);
//LiveClassroom.bbb.Enqueue(result);
//result.ImWrite($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
//var a = ConvertWriteableBitmapToBitmapImage(mWriteableBitmap);
//a.Save($"d:\\{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.png");
OnRenderVideoFrameHandler?.Invoke(width, height, rotation, mWriteableBitmap);
ImageBrush brush = new ImageBrush(mWriteableBitmap);
if (rotation > 0)
{
Matrix transform = Matrix.Identity;
double scale = (double)viewWidth / (double)viewHeight;
if (rotation == 90 || rotation == 270)
transform.ScaleAt(scale, scale, 0.5, 0.5);
transform.RotateAt(rotation, 0.5, 0.5);
brush.RelativeTransform = new MatrixTransform(transform);
}
brush.Stretch = Stretch.UniformToFill;
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
dc.DrawRectangle(brush, mPen, rect);
}
private void RenderFitMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
{
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
PixelFormat pixelFormat = PixelFormats.Pbgra32;
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
int stride = bytesPerPixel * width;
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
{
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
//Mat result = new Mat();
//result.Create(mWriteableBitmap.PixelHeight, mWriteableBitmap.PixelWidth, MatType.CV_8U, 4);
//mWriteableBitmap.CopyPixels(Int32Rect.Empty, result.Data, (int)result.Step() * result.Rows, (int)result.Step());
mInt32Rect = new Int32Rect(0, 0, width, height);
}
mWriteableBitmap.Lock();
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
mWriteableBitmap.AddDirtyRect(mInt32Rect);
mWriteableBitmap.Unlock();
OnRenderVideoFrameHandler?.Invoke(width, height, rotation, mWriteableBitmap);
ImageBrush brush = new ImageBrush(mWriteableBitmap);
if (rotation > 0)
{
Matrix transform = Matrix.Identity;
double scale = (double)viewHeight / (double)viewWidth;
if (rotation == 90 || rotation == 270)
transform.ScaleAt(1, scale, 0.5, 0.5);
transform.RotateAt(rotation, 0.5, 0.5);
brush.RelativeTransform = new MatrixTransform(transform);
}
brush.Stretch = Stretch.Uniform;
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
dc.DrawRectangle(brush, mPen, rect);
}
private void ReleaseBuffer(FrameBufferInfo info)
{
if (info.data != null)
info.data = null;
info.width = 0;
info.height = 0;
info.newFrame = false;
info.rotation = TRTCVideoRotation.TRTCVideoRotation0;
}
#region Dispose
private bool disposed = false;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
ReleaseBuffer(mArgbFrame);
mWriteableBitmap = null;
}
disposed = true;
}
~TXLiteAVVideoView()
{
this.Dispose(false);
}
#endregion
}
public class TXLiteAVVideoViewManager : ITRTCVideoRenderCallback
{
private volatile Dictionary<string, TXLiteAVVideoView> mMapViews;
public static TXLiteAVVideoViewManager sInstance;
private static Object mLocker = new Object();
public static TXLiteAVVideoViewManager GetInstance()
{
if (sInstance == null)
{
lock (mLocker)
{
if (sInstance == null)
sInstance = new TXLiteAVVideoViewManager();
}
}
return sInstance;
}
private TXLiteAVVideoViewManager()
{
mMapViews = new Dictionary<string, TXLiteAVVideoView>();
}
private string GetKey(string userId, TRTCVideoStreamType type)
{
return String.Format("{0}_{1}", userId, type);
}
// 主要用于判断当前 user 是否还有存在流画面,存在则不移除监听。
public bool HasUserId(string userId)
{
bool exit = false;
lock (mMapViews)
{
exit = mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig)) ||
mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeSub));
}
return exit;
}
public void AddView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
{
lock (mMapViews)
{
bool find = false;
foreach (var item in mMapViews)
{
if (item.Key.Equals(GetKey(userId, type)))
{
find = true;
break;
}
}
if (!find)
{
mMapViews.Add(GetKey(userId, type), view);
}
}
}
public void RemoveView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
{
lock (mMapViews)
{
foreach (var item in mMapViews.ToList())
{
if (item.Key.Equals(GetKey(userId, type)))
{
if (item.Value != null)
{
item.Value.Dispose();
}
mMapViews.Remove(item.Key);
break;
}
}
}
}
public void RemoveAllView()
{
lock (mMapViews)
mMapViews.Clear();
}
public int Count
{
get
{
lock (mMapViews)
return mMapViews.Count;
}
}
//public event Action<string, TRTCVideoStreamType, TRTCVideoFrame> OnRenderVideoFrameHandler;
/// <summary>
/// 自定义渲染回调,只能存在一个回调
/// </summary>
/// <param name="userId"></param>
/// <param name="streamType"></param>
/// <param name="frame"></param>
public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame)
{
//OnRenderVideoFrameHandler?.Invoke(userId, streamType, frame);
// 大小视频是占一个视频位,底层支持动态切换。
if (streamType == TRTCVideoStreamType.TRTCVideoStreamTypeSmall)
streamType = TRTCVideoStreamType.TRTCVideoStreamTypeBig;
TXLiteAVVideoView view = null;
lock (mMapViews)
{
foreach (var item in mMapViews)
{
if (item.Key.Equals(GetKey(userId, streamType)) && item.Value != null)
{
view = item.Value;
break;
}
}
}
if (view != null)
view.AppendVideoFrame(frame.data, (int)frame.width, (int)frame.height, frame.videoFormat, frame.rotation);
}
}
class FrameBufferInfo
{
public byte[] data { get; set; }
public int width { get; set; }
public int height { get; set; }
public bool newFrame { get; set; }
public TRTCVideoRotation rotation { get; set; }
public FrameBufferInfo()
{
rotation = TRTCVideoRotation.TRTCVideoRotation0;
newFrame = false;
width = 0;
height = 0;
data = null;
}
}
}

View File

@ -1,11 +1,19 @@
using JianGongYun.TRTC.Models;
using JianGongYun.TRTC.Components;
using JianGongYun.TRTC.Models;
using JianGongYun.TRTC.Utils;
using JianGongYun.TRTC.ViewModels;
using JianGongYun.TRTC.Windows;
using ManageLiteAV;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Window = System.Windows.Window;
namespace JianGongYun.TRTC
{
@ -52,7 +60,6 @@ namespace JianGongYun.TRTC
CurrentLiveWindow = new LiveWindow();
CurrentLiveWindow.Closed += CurrentLiveWindow_Closed;
lTRTCCloud = ITRTCCloud.getTRTCShareInstance();//创建TRTC实例
var roomPars = new TRTCParams
{
@ -66,20 +73,102 @@ namespace JianGongYun.TRTC
lTRTCCloud.enterRoom(ref roomPars, TRTCAppScene.TRTCAppSceneLIVE);//创建房间
//设备
var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
//var settingViewMode = ViewModels.SettingWindowViewModel.GetInstance();
lTXDeviceManager = lTRTCCloud.getDeviceManager();
var currentMic = settingViewMode.CurrentMic;//麦克风
var currentMic = settingWindowViewModel.CurrentMic;//麦克风
if (!string.IsNullOrEmpty(currentMic))
{
var res = lTXDeviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, currentMic);
Console.WriteLine($"设置麦克风:{res}");
}
lTXDeviceManager.setCurrentDeviceVolume(TRTCDeviceType.TXMediaDeviceTypeMic, settingWindowViewModel.MicVolume);//麦克风采集音量
lTRTCCloud.setSystemAudioLoopbackVolume(settingWindowViewModel.SytemGatherVolume);//系统声音采集音量
if (settingWindowViewModel.AudioSource == "2")
{
lTRTCCloud.startSystemAudioLoopback("");
}
else
{
lTRTCCloud.stopSystemAudioLoopback();
}
var encParams = settingWindowViewModel.EncParams;
var qosParams = settingWindowViewModel.QosParams;
var renderParams = settingWindowViewModel.RenderParams;
lTRTCCloud.setVideoEncoderParam(ref encParams);
lTRTCCloud.setNetworkQosParam(ref qosParams);
lTRTCCloud.setLocalRenderParams(ref renderParams);
//设备完结
callerWindow.Hide();//隐藏调用窗口
CurrentLiveWindow.Show();
}
private static SettingWindowViewModel settingWindowViewModel = SettingWindowViewModel.GetInstance();
/// <summary>
/// 视频画面
/// </summary>
private static Dictionary<string, TXLiteAVVideoView> VideoViews = new Dictionary<string, TXLiteAVVideoView>();
/// <summary>
/// 启动摄像头
/// </summary>
/// <param name="parent">视频容器</param>
public static void StartVideoMain(Panel parent)
{
lTRTCCloud.startLocalPreview(IntPtr.Zero);
var liveWinMode = CurrentLiveWindow.DataContext as LiveWindowViewModel;
liveWinMode.CameraRunning = true;
AddCustomVideoView(parent, CurrentClassroomEntity.TeacherId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, true);
}
/// <summary>
/// 添加自定义渲染 View 并绑定渲染回调
/// </summary>
private static void AddCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
{
TXLiteAVVideoView videoView = new TXLiteAVVideoView();
videoView.RegEngine(userId, streamType, lTRTCCloud, local);
videoView.SetRenderMode(settingWindowViewModel.RenderParams.fillMode);
videoView.Width = parent.ActualWidth;
videoView.Height = parent.ActualHeight;
parent.Children.Add(videoView);
string key = string.Format("{0}_{1}", userId, streamType);
VideoViews.Add(key, videoView);
}
/// <summary>
/// 移除自定义渲染 View 并解绑渲染回调
/// </summary>
private static void RemoveCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
{
TXLiteAVVideoView videoView = null;
string key = string.Format("{0}_{1}", userId, streamType);
if (VideoViews.TryGetValue(key, out videoView))
{
videoView.RemoveEngine(lTRTCCloud);
parent.Children.Remove(videoView);
VideoViews.Remove(key);
}
}
/// <summary>
/// 重启音频录制
/// </summary>
public static void RestartAudio() { }
/// <summary>
/// 重设主视频(摄像头)
/// </summary>
public static void ResetVideoMain() { }
/// <summary>
/// 重设主视频(摄像头)网络
/// </summary>
public static void ResetVideoMainQos() { }
/// <summary>
/// 重设副视频(录屏)
/// </summary>
public static void ResetVideoSub() { }
private static void CurrentLiveWindow_Closed(object sender, EventArgs e)
{

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace JianGongYun.TRTC.Models
{
public enum LiveTypeEnum
{
CameraAndScreen = 0,
OnlyScreen,
OnlyCamera,
OnlyAudio,
}
}

View File

@ -0,0 +1,27 @@
using JianGongYun.TRTC.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Data;
namespace JianGongYun.TRTC
{
public class LiveTypeToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString() == parameter.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isChecked = (bool)value;
if (!isChecked)
{
return null;
}
return (LiveTypeEnum)Enum.Parse(typeof(LiveTypeEnum), parameter.ToString());
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace JianGongYun.TRTC
{
/// <summary>
/// 把bool转换为相反的控件显示状态内置的BooleanToVisibilityConverter的true为显示false为隐藏
/// </summary>
public class UnBooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool flag = false;
if (value is bool)
{
flag = (bool)value;
}
else if (value is bool?)
{
bool? nullable = (bool?)value;
flag = nullable.HasValue ? nullable.Value : false;
}
return (flag ? Visibility.Hidden : Visibility.Visible);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

View File

@ -0,0 +1,32 @@
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Media.Imaging;
namespace JianGongYun.TRTC.Utils
{
public static class WriteableBitmapToMat
{
/// <summary>
/// WriteableBitmap转Mat
/// </summary>
/// <param name="writeableBitmap"></param>
/// <returns></returns>
public static Mat ToMat(this WriteableBitmap writeableBitmap)
{
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new JpegBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(writeableBitmap));
enc.Save(outStream);
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(outStream))
{
var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
return mat;
}
}
}
}
}

View File

@ -1,8 +1,11 @@
using System;
using JianGongYun.TRTC.Models;
using ManageLiteAV;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows.Threading;
namespace JianGongYun.TRTC.ViewModels
{
@ -44,6 +47,15 @@ namespace JianGongYun.TRTC.ViewModels
set
{
_IsLive = value;
if (value)//开始直播,清空时间并开始计时
{
_LiveTimeCount = new DateTime(1970, 1, 1, 0, 0, 0);
timer.Start();
}
else
{
timer.Stop();
}
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsLive"));
@ -55,5 +67,147 @@ namespace JianGongYun.TRTC.ViewModels
}
}
public LiveWindowViewModel()
{
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += new EventHandler((a, b) => LiveTimeCount = "");
}
/// <summary>
/// 直播计时器
/// </summary>
private DispatcherTimer timer = null;
private DateTime _LiveTimeCount;
public string LiveTimeCount
{
get
{
return _LiveTimeCount.ToString("HH:mm:ss");
}
set
{
_LiveTimeCount = _LiveTimeCount.AddSeconds(1);
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveTimeCount"));
}
}
}
/// <summary>
/// 直播类型
/// </summary>
private LiveTypeEnum _LiveType = LiveTypeEnum.OnlyAudio;
public LiveTypeEnum LiveType
{
set
{
_LiveType = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveType"));
}
}
get
{
return _LiveType;
}
}
/// <summary>
/// 摄像头采集中
/// </summary>
private bool _CameraRunning = false;
public bool CameraRunning
{
set
{
_CameraRunning = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("CameraRunning"));
}
}
get
{
return _CameraRunning;
}
}
/// <summary>
/// 屏幕分享中
/// </summary>
private bool _ScreenRunning = false;
public bool ScreenRunning
{
set
{
_ScreenRunning = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRunning"));
}
}
get
{
return _ScreenRunning;
}
}
/// <summary>
/// 麦克风使用中
/// </summary>
private bool _MicRunning = false;
public bool MicRunning
{
set
{
_MicRunning = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("MicRunning"));
}
}
get
{
return _MicRunning;
}
}
private SIZE thumbSize = new SIZE { cx = 300, cy = 200 };
private SIZE iconSize = new SIZE { cx = 50, cy = 50 };
private ObservableCollection<TRTCScreenCaptureSourceInfo> _LiveScreens = new ObservableCollection<TRTCScreenCaptureSourceInfo>();
/// <summary>
/// 可分享桌面
/// </summary>
public ObservableCollection<TRTCScreenCaptureSourceInfo> LiveScreens
{
get
{
_LiveScreens.Clear();
var temp = LiveClassroom.lTRTCCloud.getScreenCaptureSources(ref thumbSize, ref iconSize);
var count = temp.getCount();
for (uint i = 0; i < count; i++)
{
_LiveScreens.Add(temp.getSourceInfo(i));
}
temp.release();
return _LiveScreens;
}
}
private IntPtr _CurrentShareScreen;
public IntPtr CurrentShareScreen
{
get { return _CurrentShareScreen; }
set
{
_CurrentShareScreen = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("CurrentShareScreen"));
}
}
}
}
}

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Windows.Controls;
using JianGongYun.TRTC.Components;
using System.Windows;
using ManageLiteAV;
namespace JianGongYun.TRTC.ViewModels
{
@ -40,7 +41,7 @@ namespace JianGongYun.TRTC.ViewModels
}
}
#region
#region
/// <summary>
/// 集合,实时获取
/// </summary>
@ -140,10 +141,6 @@ namespace JianGongYun.TRTC.ViewModels
}
#endregion
#region
/// <summary>
/// 音频来源
/// </summary>
@ -169,7 +166,7 @@ namespace JianGongYun.TRTC.ViewModels
storage.SetValue(INI_ROOT_KEY, INI_KEY_AUDIO_SOURCE, value);//生成保存本地
if (_AudioSource == "1")//只采集麦克风,关闭系统音采集
{
ShowSytemGatherSlider = Visibility.Hidden;
ShowSytemGatherSlider = Visibility.Collapsed;
LiveClassroom.lTRTCCloud.stopSystemAudioLoopback();
}
else if (_AudioSource == "2")//麦和系统音,开启采集系统音
@ -187,18 +184,18 @@ namespace JianGongYun.TRTC.ViewModels
/// <summary>
/// 是否显示系统采集滑动条
/// </summary>
private Visibility _ShowSytemGatherSlider = Visibility.Hidden;
private Visibility _ShowSytemGatherSlider = Visibility.Collapsed;
public Visibility ShowSytemGatherSlider
{
get
{
if (AudioSource=="2")
if (AudioSource == "2")
{
_ShowSytemGatherSlider = Visibility.Visible;
}
else
{
_ShowSytemGatherSlider = Visibility.Hidden;
_ShowSytemGatherSlider = Visibility.Collapsed;
}
return _ShowSytemGatherSlider;
}
@ -246,6 +243,397 @@ namespace JianGongYun.TRTC.ViewModels
#endregion
#region
/// <summary>
/// 视频帧率(fps)
/// </summary>
private string _ScreenRecordingFps = "60";
public string ScreenRecordingFps
{
get
{
var screenRecordingFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS);//本地缓存
if (string.IsNullOrEmpty(screenRecordingFps))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS, _ScreenRecordingFps);//生成初始数据
}
else
{
_ScreenRecordingFps = screenRecordingFps;
}
return _ScreenRecordingFps;
}
set
{
_ScreenRecordingFps = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_FPS, value);//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingFps"));
}
}
}
/// <summary>
/// 音频码率
/// </summary>
private string _ScreenRecordingAudioBitrate = "320000";
public string ScreenRecordingAudioBitrate
{
get
{
var screenRecordingAudioBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE);//本地缓存
if (string.IsNullOrEmpty(screenRecordingAudioBitrate))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE, _ScreenRecordingAudioBitrate);//生成初始数据
}
else
{
_ScreenRecordingAudioBitrate = screenRecordingAudioBitrate;
}
return _ScreenRecordingAudioBitrate;
}
set
{
_ScreenRecordingAudioBitrate = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE, value);//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingAudioBitrate"));
}
}
}
/// <summary>
/// 音频采样率
/// </summary>
private string _ScreenRecordingAudioFreq = "48000";
public string ScreenRecordingAudioFreq
{
get
{
var screenRecordingAudioFreq = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ);//本地缓存
if (string.IsNullOrEmpty(screenRecordingAudioFreq))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ, _ScreenRecordingAudioFreq);//生成初始数据
}
else
{
_ScreenRecordingAudioFreq = screenRecordingAudioFreq;
}
return _ScreenRecordingAudioFreq;
}
set
{
_ScreenRecordingAudioFreq = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_AUDIO_FREQ, value);//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingAudioFreq"));
}
}
}
/// <summary>
/// 编码级别
/// </summary>
private string _ScreenRecordingProfileLevel = "-profile:v high -level 5.1";
public string ScreenRecordingProfileLevel
{
get
{
var screenRecordingProfileLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL);//本地缓存
if (string.IsNullOrEmpty(screenRecordingProfileLevel))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL, _ScreenRecordingProfileLevel);//生成初始数据
}
else
{
_ScreenRecordingProfileLevel = screenRecordingProfileLevel;
}
return _ScreenRecordingProfileLevel;
}
set
{
_ScreenRecordingProfileLevel = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL, value);//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingProfileLevel"));
}
}
}
/// <summary>
/// 录制倒计时
/// </summary>
private int _ScreenRecordingCountdown = 3;
public int ScreenRecordingCountdown
{
get
{
var screenRecordingCountdown = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN);//本地缓存
if (string.IsNullOrEmpty(screenRecordingCountdown))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN, _ScreenRecordingCountdown.ToString());//生成初始数据
}
else
{
_ScreenRecordingCountdown = int.Parse(screenRecordingCountdown);
}
return _ScreenRecordingCountdown;
}
set
{
_ScreenRecordingCountdown = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_COUNTDOWN, value.ToString());//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingCountdown"));
}
}
}
/// <summary>
/// 视频保存路径
/// </summary>
private string _ScreenRecordingDir;
public string ScreenRecordingDir
{
get
{
var screenRecordingDir = storage.GetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR);//本地缓存
if (string.IsNullOrEmpty(screenRecordingDir))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR, _ScreenRecordingDir);//生成初始数据
}
else
{
_ScreenRecordingDir = screenRecordingDir;
}
return _ScreenRecordingDir;
}
set
{
_ScreenRecordingDir = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_SCREEN_RECORDING_DIR, value.ToString());//生成保存本地
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ScreenRecordingDir"));
}
}
}
#endregion
#region
/// <summary>
/// 音频质量
/// </summary>
private TRTCAudioQuality _LiveAudioLevel = TRTCAudioQuality.TRTCAudioQualityDefault;
public TRTCAudioQuality LiveAudioLevel
{
get
{
var liveAudioLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL);//本地缓存
if (string.IsNullOrEmpty(liveAudioLevel))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL, _LiveAudioLevel.ToString());//生成初始数据
}
else
{
_LiveAudioLevel = (TRTCAudioQuality)Enum.Parse(typeof(TRTCAudioQuality), liveAudioLevel);
}
return _LiveAudioLevel;
}
set
{
_LiveAudioLevel = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_AUDIO_LEVEL, value.ToString());//生成保存本地
LiveClassroom.RestartAudio();//重启音频
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveAudioLevel"));
}
}
}
/// <summary>
/// 摄像画面帧率
/// </summary>
private uint _LiveMainFps = 24;
public uint LiveMainFps
{
get
{
var liveMainFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS);//本地缓存
if (string.IsNullOrEmpty(liveMainFps))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS, _LiveMainFps.ToString());//生成初始数据
}
else
{
_LiveMainFps = uint.Parse(liveMainFps);
}
return _LiveMainFps;
}
set
{
_LiveMainFps = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_FPS, value.ToString());//生成保存本地
LiveClassroom.ResetVideoMain();//重设参数
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainFps"));
}
}
}
/// <summary>
/// 摄像画面码率
/// </summary>
private uint _LiveMainBitrate = 1600;
public uint LiveMainBitrate
{
get
{
var liveMainBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE);//本地缓存
if (string.IsNullOrEmpty(liveMainBitrate))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE, _LiveMainBitrate.ToString());//生成初始数据
}
else
{
_LiveMainBitrate = uint.Parse(liveMainBitrate);
}
return _LiveMainBitrate;
}
set
{
_LiveMainBitrate = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_BITTRATE, value.ToString());//生成保存本地
LiveClassroom.ResetVideoMain();//重设参数
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainBitrate"));
}
}
}
/// <summary>
/// 摄像画面级别
/// </summary>
private TRTCVideoQosPreference _LiveMainLevel = TRTCVideoQosPreference.TRTCVideoQosPreferenceClear;
public TRTCVideoQosPreference LiveMainLevel
{
get
{
var liveMainLevel = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL);//本地缓存
if (string.IsNullOrEmpty(liveMainLevel))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL, _LiveMainLevel.ToString());//生成初始数据
}
else
{
_LiveMainLevel = (TRTCVideoQosPreference)Enum.Parse(typeof(TRTCVideoQosPreference), liveMainLevel);
}
return _LiveMainLevel;
}
set
{
_LiveMainLevel = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_MAIN_LEVEL, value.ToString());//生成保存本地
LiveClassroom.ResetVideoMainQos();//重设参数
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveMainLevel"));
}
}
}
/// <summary>
/// 屏幕分享帧率
/// </summary>
private uint _LiveSubFps = 24;
public uint LiveSubFps
{
get
{
var liveSubFps = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS);//本地缓存
if (string.IsNullOrEmpty(liveSubFps))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS, _LiveSubFps.ToString());//生成初始数据
}
else
{
_LiveSubFps = uint.Parse(liveSubFps);
}
return _LiveSubFps;
}
set
{
_LiveSubFps = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_FPS, value.ToString());//生成保存本地
LiveClassroom.ResetVideoSub();//重新设置副画面参数
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveSubFps"));
}
}
}
/// <summary>
/// 屏幕分享码率
/// </summary>
private uint _LiveSubBitrate = 2000;
public uint LiveSubBitrate
{
get
{
var liveSubBitrate = storage.GetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE);//本地缓存
if (string.IsNullOrEmpty(liveSubBitrate))
{
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE, _LiveSubBitrate.ToString());//生成初始数据
}
else
{
_LiveSubBitrate = uint.Parse(liveSubBitrate);
}
return _LiveSubBitrate;
}
set
{
_LiveSubBitrate = value;
storage.SetValue(INI_ROOT_KEY, INI_KEY_LIVE_SUB_BITTRATE, value.ToString());//生成保存本地
LiveClassroom.ResetVideoSub();//重启音频
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LiveSubBitrate"));
}
}
}
#endregion
#region
public TRTCVideoEncParam EncParams
{
get
{
return new TRTCVideoEncParam { enableAdjustRes = true, resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape, videoBitrate = LiveMainBitrate, videoFps = LiveMainFps };
}
}
public TRTCNetworkQosParam QosParams
{
get
{
return new TRTCNetworkQosParam { preference = LiveMainLevel };
}
}
public TRTCRenderParams RenderParams
{
get
{
return new TRTCRenderParams { fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Enable, rotation = TRTCVideoRotation.TRTCVideoRotation0 };
}
}
#endregion
/// <summary>
/// ini文件操作
@ -254,6 +642,7 @@ namespace JianGongYun.TRTC.ViewModels
private SettingWindowViewModel()
{
storage = new IniStorage(sPath);
_ScreenRecordingDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonVideos);
}
#region
@ -261,44 +650,29 @@ namespace JianGongYun.TRTC.ViewModels
//配置文件路径
private string sPath = ".\\TRTCConfig.ini";
//根节点
public const string INI_ROOT_KEY = "TRTCLOCALCONFIG";
// 设备
public const string INI_KEY_CHOOSE_CAMERA = "INI_KEY_CHOOSE_CAMERA";//当前摄像头
public const string INI_KEY_CHOOSE_MIC = "INI_KEY_CHOOSE_MIC";//当前麦克风
// 音频
public const string INI_KEY_AUDIO_MIC_VOLUME = "INI_KEY_AUDIO_MIC_VOLUME";//麦克风音量
public const string INI_KEY_AUDIO_SPEAKER_VOLUME = "INI_KEY_AUDIO_SOURCE";//播放音量
public const string INI_KEY_AUDIO_SOURCE = "INI_KEY_AUDIO_SOURCE";//音频来源
public const string INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME = "INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME";//麦克风音量
// 视频
public const string INI_KEY_VIDEO_FPS = "INI_KEY_VIDEO_FPS";//视频FPS
public const string INI_KEY_VIDEO_BITRATE = "INI_KEY_VIDEO_BITRATE";
public const string INI_KEY_VIDEO_RESOLUTION = "INI_KEY_VIDEO_RESOLUTION";
public const string INI_KEY_VIDEO_RES_MODE = "INI_KEY_VIDEO_RES_MODE";
public const string INI_KEY_VIDEO_QUALITY = "INI_KEY_VIDEO_QUALITY";
public const string INI_KEY_VIDEO_QUALITY_CONTROL = "INI_KEY_VIDEO_QUALITY_CONTROL";
public const string INI_KEY_VIDEO_APP_SCENE = "INI_KEY_VIDEO_APP_SCENE";
public const string INI_KEY_VIDEO_FILL_MODE = "INI_KEY_VIDEO_FILL_MODE";
public const string INI_KEY_VIDEO_ROTATION = "INI_KEY_VIDEO_ROTATION";
// 美颜
public const string INI_KEY_BEAUTY_OPEN = "INI_KEY_BEAUTY_OPEN";
public const string INI_KEY_BEAUTY_STYLE = "INI_KEY_BEAUTY_STYLE";
public const string INI_KEY_BEAUTY_VALUE = "INI_KEY_BEAUTY_VALUE";
public const string INI_KEY_WHITE_VALUE = "INI_KEY_WHITE_VALUE";
public const string INI_KEY_RUDDINESS_VALUE = "INI_KEY_RUDDINESS_VALUE";
// 大小流
public const string INI_KEY_SET_PUSH_SMALLVIDEO = "INI_KEY_SET_PUSH_SMALLVIDEO";
public const string INI_KEY_SET_PLAY_SMALLVIDEO = "INI_KEY_SET_PLAY_SMALLVIDEO";
// 测试
public const string INI_KEY_SET_NETENV_STYLE = "INI_KEY_SET_NETENV_STYLE";
public const string INI_KEY_ROOMCALL_STYLE = "INI_KEY_ROOMCALL_STYLE";
// 镜像
public const string INI_KEY_LOCAL_VIDEO_MIRROR = "INI_KEY_LOCAL_VIDEO_MIRROR";
public const string INI_KEY_REMOTE_VIDEO_MIRROR = "INI_KEY_REMOTE_VIDEO_MIRROR";
// 音量提示
public const string INI_KEY_SHOW_AUDIO_VOLUME = "INI_KEY_SHOW_AUDIO_VOLUME";
// 混流
public const string INI_KEY_CLOUD_MIX_TRANSCODING = "INI_KEY_CLOUD_MIX_TRANSCODING";
private const string INI_ROOT_KEY = "TRTCLOCALCONFIG";
//音频
private const string INI_KEY_CHOOSE_MIC = "INI_KEY_CHOOSE_MIC";//当前麦克风
private const string INI_KEY_AUDIO_MIC_VOLUME = "INI_KEY_AUDIO_MIC_VOLUME";//麦克风音量
private const string INI_KEY_AUDIO_SPEAKER_VOLUME = "INI_KEY_AUDIO_SOURCE";//播放音量
private const string INI_KEY_AUDIO_SOURCE = "INI_KEY_AUDIO_SOURCE";//音频来源
private const string INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME = "INI_KEY_AUDIO_SYSTEM_GATHER_VOLUME";//麦克风音量
//录屏
private const string INI_KEY_SCREEN_RECORDING_FPS = "INI_KEY_SCREEN_RECORDING_FPS";//视频帧率(fps)
private const string INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE = "INI_KEY_SCREEN_RECORDING_AUDIO_BITRATE";//音频码率
private const string INI_KEY_SCREEN_RECORDING_AUDIO_FREQ = "INI_KEY_SCREEN_RECORDING_AUDIO_FREQ";//音频采样率
private const string INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL = "INI_KEY_SCREEN_RECORDING_PROFILE_LEVEL";//编码级别
private const string INI_KEY_SCREEN_RECORDING_COUNTDOWN = "INI_KEY_SCREEN_RECORDING_COUNTDOWN";//录制倒计时
private const string INI_KEY_SCREEN_RECORDING_DIR = "INI_KEY_SCREEN_RECORDING_DIR";//录制保存路径
//直播
private const string INI_KEY_LIVE_AUDIO_LEVEL = "INI_KEY_LIVE_AUDIO_LEVEL";//直播音频等级
private const string INI_KEY_LIVE_MAIN_FPS = "INI_KEY_LIVE_MAIN_FPS";//直播主帧率
private const string INI_KEY_LIVE_MAIN_BITTRATE = "INI_KEY_LIVE_MAIN_BITTRATE";//直播主码率
private const string INI_KEY_LIVE_MAIN_LEVEL = "INI_KEY_LIVE_MAIN_LEVEL";//主画面级别
private const string INI_KEY_LIVE_SUB_FPS = "INI_KEY_LIVE_SUB_FPS";//屏幕分享帧率
private const string INI_KEY_LIVE_SUB_BITTRATE = "INI_KEY_LIVE_SUB_BITTRATE";//屏幕分享码率
#endregion
}
}

View File

@ -14,7 +14,14 @@
Background="#232428">
<!--窗口填满-->
<Metro:MetroWindow.Resources>
<Geometry x:Key="Icon_Browser">M512 884.363636c-50.059636 0-98.722909-9.890909-144.64-29.393454a372.922182 372.922182 0 0 1-118.365091-79.965091 372.922182 372.922182 0 0 1-79.965091-118.365091A367.872 367.872 0 0 1 139.636364 512c0-50.036364 9.890909-98.722909 29.393454-144.64a372.945455 372.945455 0 0 1 79.965091-118.365091 372.922182 372.922182 0 0 1 118.365091-79.965091A367.872 367.872 0 0 1 512 139.636364c50.059636 0 98.722909 9.890909 144.64 29.393454a372.945455 372.945455 0 0 1 118.365091 79.965091 372.922182 372.922182 0 0 1 79.965091 118.365091A367.872 367.872 0 0 1 884.363636 512c0 50.059636-9.890909 98.722909-29.393454 144.64a372.945455 372.945455 0 0 1-79.965091 118.365091 372.922182 372.922182 0 0 1-118.365091 79.965091A367.848727 367.848727 0 0 1 512 884.363636z m0-698.181818c-43.776 0-86.341818 8.634182-126.464 25.693091a326.516364 326.516364 0 0 0-103.633455 70.050909 326.516364 326.516364 0 0 0-70.027636 103.610182A321.629091 321.629091 0 0 0 186.181818 512c0 43.776 8.634182 86.341818 25.693091 126.464a326.516364 326.516364 0 0 0 70.050909 103.633455 326.516364 326.516364 0 0 0 103.610182 70.027636A321.652364 321.652364 0 0 0 512 837.818182c43.776 0 86.341818-8.657455 126.464-25.693091a326.516364 326.516364 0 0 0 103.633455-70.050909 326.516364 326.516364 0 0 0 70.027636-103.610182A321.652364 321.652364 0 0 0 837.818182 512c0-43.776-8.657455-86.341818-25.693091-126.464a326.516364 326.516364 0 0 0-70.050909-103.633455 326.516364 326.516364 0 0 0-103.610182-70.027636A321.652364 321.652364 0 0 0 512 186.181818z m-170.077091 512.162909a18.013091 18.013091 0 0 1-17.408-22.667636l70.865455-265.774546a18.013091 18.013091 0 0 1 12.753454-12.753454l265.774546-70.865455a18.013091 18.013091 0 0 1 22.039272 22.039273l-70.865454 265.774546a18.013091 18.013091 0 0 1-12.776727 12.753454L346.554182 697.716364a18.013091 18.013091 0 0 1-4.654546 0.628363z m85.573818-269.079272l-60.16 225.62909 225.605818-60.16 60.16-225.62909-225.605818 60.16z m111.755637 126.138181a17.966545 17.966545 0 0 1-12.730182-5.282909l-46.801455-46.778182a18.013091 18.013091 0 1 1 25.483637-25.506909l46.778181 46.801455a18.013091 18.013091 0 0 1-12.730181 30.766545z</Geometry>
<Geometry x:Key="Icon_Setting">M372.134088 1004.846981a509.94041 509.94041 0 0 1-159.298198-76.821527l2.164315-103.514738a93.088793 93.088793 0 0 0-74.238313-93.088794l-101.536602-20.991523A509.428422 509.428422 0 0 1 0.011636 537.983409l82.243949-62.834935a93.088793 93.088793 0 0 0 26.507034-116.104998l-46.89348-92.390627A514.152678 514.152678 0 0 1 172.225904 128.415991l100.419536 25.133974a93.088793 93.088793 0 0 0 107.284834-51.664281l43.007023-94.252403a515.246472 515.246472 0 0 1 88.434354-7.610009c30.137497 0 59.669917 2.606486 88.411081 7.610009l43.007023 94.252403a93.088793 93.088793 0 0 0 107.284834 51.664281l100.396264-25.133974a514.152678 514.152678 0 0 1 110.356765 138.236858l-46.870208 92.390627a93.088793 93.088793 0 0 0 26.483762 116.104998l82.243949 62.834935a509.428422 509.428422 0 0 1-39.213654 172.44699l-101.51333 20.968251a93.088793 93.088793 0 0 0-74.238312 93.088793l2.141042 103.538011a509.94041 509.94041 0 0 1-159.298198 76.798255l-79.684007-66.279221a93.088793 93.088793 0 0 0-119.060567 0l-79.684007 66.302493zM511.348378 721.461421a209.449785 209.449785 0 1 0 0-418.89957 209.449785 209.449785 0 0 0 0 418.89957z</Geometry>
<Geometry x:Key="Icon_Camera">M512 85.33312C323.499138 85.33312 170.66752 238.164738 170.66752 426.6656s152.831618 341.33248 341.33248 341.33248 341.33248-152.831618 341.33248-341.33248S700.500862 85.33312 512 85.33312zM85.3344 426.6656C85.3344 191.032411 276.366811 0 512 0c235.661633 0 426.6656 191.032411 426.6656 426.6656 0 235.661633-191.003967 426.6656-426.6656 426.6656-235.633189 0-426.6656-191.003967-426.6656-426.6656z m127.99968 554.66528A42.66656 42.66656 0 0 1 256.00064 938.66432h511.99872a42.66656 42.66656 0 1 1 0 85.33312H256.00064a42.66656 42.66656 0 0 1-42.66656-42.66656z M459.776131 775.166062a42.239894 42.239894 0 0 1 19.114618 56.888747l-85.560675 169.642242a42.951004 42.951004 0 0 1-56.774969 17.806178 42.239894 42.239894 0 0 1-19.71195-55.722527l85.560675-169.642243a42.951004 42.951004 0 0 1 57.372301-18.972397z m132.892112 0a42.239894 42.239894 0 0 0-19.114619 56.888747l85.560675 169.642242a42.951004 42.951004 0 0 0 56.774969 17.806178 42.239894 42.239894 0 0 0 19.711951-55.722527l-85.560675-169.642243a42.951004 42.951004 0 0 0-57.372301-18.972397zM526.222187 321.136975c-61.439846 0-111.2175 49.350988-111.2175 110.250391 0 60.927848 49.777653 110.278835 111.2175 110.278835s111.2175-49.350988 111.217499-110.278835c0-60.870959-49.777653-110.250391-111.217499-110.250391z m-196.806619 110.250391c0-107.747286 88.120669-195.099957 196.806619-195.099957 108.685951 0 196.806619 87.352671 196.806619 195.128401 0 107.747286-88.120669 195.099957-196.806619 195.099957-108.685951 0-196.806619-87.352671-196.806619-195.128401zM526.222187 28.444373c23.60883 0 42.780337 19.000841 42.780337 42.410561v63.630063c0 23.409719-19.143063 42.382116-42.780337 42.382116-23.60883 0-42.780337-18.972397-42.780338-42.382116V70.82649c0-23.409719 19.143063-42.410561 42.780338-42.410561z</Geometry>
<Geometry x:Key="Icon_Screen">M864 159.872L160 160c-17.696 0-32 14.176-32 31.872v448a32 32 0 0 0 32 32h704a32 32 0 0 0 32-32v-448a32 32 0 0 0-32-32zM864 640H160V191.872h704V640z M928 32H96a96 96 0 0 0-96 96v640a95.904 95.904 0 0 0 95.68 95.936H416v38.944l-199.744 25.952A31.968 31.968 0 0 0 224 991.872h576a32 32 0 0 0 7.744-63.072L608 902.88v-38.944h320.32A95.904 95.904 0 0 0 1024 768V128a96 96 0 0 0-96-96z m32 736c0 17.632-14.368 32-32 32H96c-17.664 0-32-14.368-32-32V128a32 32 0 0 1 32-32h832c17.632 0 32 14.336 32 32v640z</Geometry>
<Geometry x:Key="Icon_Mic">M486.4 972.8v-128.9728A332.8 332.8 0 0 1 179.2 512a25.6 25.6 0 0 1 51.2 0 281.6 281.6 0 0 0 563.2 0 25.6 25.6 0 1 1 51.2 0 332.8 332.8 0 0 1-307.2 331.8272V972.8h153.6a25.6 25.6 0 1 1 0 51.2h-358.4a25.6 25.6 0 1 1 0-51.2h153.6zM512 51.2a153.6 153.6 0 0 0-153.6 153.6v307.2a153.6 153.6 0 0 0 307.2 0V204.8a153.6 153.6 0 0 0-153.6-153.6z m0-51.2a204.8 204.8 0 0 1 204.8 204.8v307.2a204.8 204.8 0 1 1-409.6 0V204.8a204.8 204.8 0 0 1 204.8-204.8z</Geometry>
<Geometry x:Key="Icon_User">M511.626 1.896C229.572 1.896 0.927 230.541 0.927 512.595c0 282.055 228.645 510.699 510.699 510.699s510.698-228.645 510.698-510.699S793.68 1.896 511.626 1.896z m0 69.641c243.606 0 441.058 197.474 441.058 441.058 0 87.347-25.392 168.762-69.194 237.271-73.419-77.609-170.944-132.204-280.597-151.829 70.004-33.755 118.404-105.164 118.404-188.066 0-115.388-93.535-208.922-208.923-208.922S303.452 294.583 303.452 409.97c0 82.902 48.399 154.311 118.403 188.066-110.093 19.704-207.96 74.661-281.479 152.77-44.177-68.704-69.808-150.465-69.808-238.211 0-243.584 197.496-441.058 441.058-441.058z</Geometry>
<BooleanToVisibilityConverter x:Key="VisibilityOfBool" />
<live:UnBooleanToVisibilityConverter x:Key="UnVisibilityOfBool" />
<live:LiveTypeToBoolConverter x:Key="LiveTypeConverter"></live:LiveTypeToBoolConverter>
</Metro:MetroWindow.Resources>
<Canvas x:Name="Root" Background="Transparent">
<!--父容器填满-->
@ -34,6 +41,13 @@
<TextBlock FontSize="14" Foreground="#3d7cf9" Text="{Binding StudentCount,Mode=OneWay}"></TextBlock>
<TextBlock FontSize="14" Padding="3 0 0 0" Foreground="#bbbbbb" Text="人"></TextBlock>
</StackPanel>
<Metro:AduFlatButton Content="开始直播" Click="StartLive_Click" Tag="True" Canvas.Bottom="13" Canvas.Right="25" Visibility="{Binding IsLive, Converter={StaticResource UnVisibilityOfBool}}"></Metro:AduFlatButton>
<Metro:AduFlatButton Content="结束直播" Click="StartLive_Click" Tag="False" Type="error" Canvas.Bottom="13" Canvas.Right="25" Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}"></Metro:AduFlatButton>
<StackPanel Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}" Orientation="Horizontal" Canvas.Bottom="20" Canvas.Right="150">
<Ellipse VerticalAlignment="Center" Width="10" Fill="LawnGreen" Height="10"></Ellipse>
<TextBlock FontSize="15" Foreground="White" Margin="7 0 0 0">直播中</TextBlock>
<TextBlock FontSize="15" Foreground="White" Margin="7 0 0 0" Text="{Binding LiveTimeCount}"></TextBlock>
</StackPanel>
</Canvas>
<!--右方聊天学员面板-->
<Canvas DockPanel.Dock="Right" Width="280" Background="#2f3035">
@ -44,12 +58,108 @@
<!--下方设置面板-->
<Canvas DockPanel.Dock="Bottom" Height="70" Background="#232428">
<!--设置按钮-->
<Metro:AduSysButton Click="Setting_Btn_Click" Foreground="#fff" Canvas.Left="20" Canvas.Top="15" CornerRadius="6" Height="40" Width="40" Icon="{StaticResource Icon_Browser}" Content="" />
<Button Click="Setting_Btn_Click" Style="{StaticResource CusIconBtn}" Canvas.Left="27" Canvas.Top="15" Background="Transparent" BorderThickness="0">
<Button.Content>
<StackPanel>
<Path Width="18" Height="18" Fill="#fff" Shape.Stretch="Fill" Data="{StaticResource Icon_Setting}" />
<TextBlock Foreground="#fff" Margin="0 3 0 0">设置</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</Canvas>
<!--中间面板-->
<Canvas Background="#151618">
<Canvas x:Name="CusContent" Background="#151618">
<!--直播前-->
<Grid Canvas.Top="0" Canvas.Left="0" Height="{Binding ElementName=CusContent,Path=ActualHeight}" Width="{Binding ElementName=CusContent,Path=ActualWidth}" Visibility="{Binding IsLive, Converter={StaticResource UnVisibilityOfBool}}">
<StackPanel Width="700" VerticalAlignment="Center">
<TextBlock FontSize="30" Foreground="#999999" HorizontalAlignment="Center">请选择授课方式</TextBlock>
<TextBlock HorizontalAlignment="Center" FontSize="16" Margin="0 10 0 0" Foreground="#999999">您可在上课期间随时调整授课方式</TextBlock>
<Grid Margin="0 30 0 0" Height="300">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid Margin="5" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" Background="#2f3035">
<Canvas x:Name="CameraPrew">
<Grid Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Height="{Binding ElementName=CameraPrew,Path=ActualHeight}" Canvas.Top="0" Canvas.Left="0">
<Path Margin="0 0 0 30" Width="111" Height="111" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_User}" />
</Grid>
<Grid x:Name="BeforeLiveViewWrap" Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Height="{Binding ElementName=CameraPrew,Path=ActualHeight}" Canvas.Top="0" Canvas.Left="0"></Grid>
<TextBlock Width="{Binding ElementName=CameraPrew,Path=ActualWidth}" Canvas.Bottom="0" Canvas.Left="0" Padding="5" FontSize="14" Foreground="#cccccc" Background="#65888888" TextAlignment="Center">摄像头预览</TextBlock>
</Canvas>
</Grid>
<Grid Margin="5" Background="#2f3035" Grid.Row="0" Grid.Column="2">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Margin="0 0 0 20" HorizontalAlignment="Center" Orientation="Horizontal">
<Path Width="30" Height="35" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Camera}" />
<TextBlock FontSize="30" Margin="10 0" Foreground="#cccccc">+</TextBlock>
<Path Width="30" Height="30" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Screen}" />
</StackPanel>
<Metro:AduRadioButton x:Name="Rad1" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="摄像头+屏幕分享" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=CameraAndScreen}" />
</StackPanel>
</Grid>
<Grid Margin="5" Background="#2f3035" Grid.Row="0" Grid.Column="3">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Path Margin="0 0 0 30" Width="30" Height="30" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Screen}" />
<Metro:AduRadioButton x:Name="Rad2" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="屏幕分享" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyScreen}" />
</StackPanel>
</Grid>
<Grid Margin="5" Background="#2f3035" Grid.Row="1" Grid.Column="2">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Path Margin="0 0 0 25" Width="30" Height="35" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Camera}" />
<Metro:AduRadioButton x:Name="Rad3" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="摄像头" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyCamera}" />
</StackPanel>
</Grid>
<Grid Margin="5" Background="#2f3035" Grid.Row="1" Grid.Column="3">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Path Margin="0 0 0 15" Width="30" Height="45" Fill="#cccccc" Shape.Stretch="Fill" Data="{StaticResource Icon_Mic}" />
<Metro:AduRadioButton x:Name="Rad4" Click="Tpye_Click" GroupName="LiveType" Foreground="#cccccc" Content="仅声音" FontSize="14" IconWidth="16" IsChecked="{Binding LiveType,Converter={StaticResource LiveTypeConverter},ConverterParameter=OnlyAudio}" />
</StackPanel>
</Grid>
</Grid>
</StackPanel>
</Grid>
<!--直播中-->
<Grid Canvas.Top="0" Canvas.Left="0" Height="{Binding ElementName=CusContent,Path=ActualHeight}" Width="{Binding ElementName=CusContent,Path=ActualWidth}" Visibility="{Binding IsLive, Converter={StaticResource VisibilityOfBool}}">
<TextBlock Foreground="White">true</TextBlock>
</Grid>
</Canvas>
</DockPanel>
<Grid x:Name="CountdownWrap" Visibility="Hidden" Canvas.Top="0" Canvas.Left="0" Background="Transparent" Panel.ZIndex="10" Height="{Binding ElementName=Root,Path=ActualHeight}" Width="{Binding ElementName=Root,Path=ActualWidth}"></Grid>
<Grid x:Name="ShareScreenListWrap" Visibility="Visible" Canvas.Top="0" Canvas.Left="0" Background="Transparent" Panel.ZIndex="5" Height="{Binding ElementName=Root,Path=ActualHeight}" Width="{Binding ElementName=Root,Path=ActualWidth}">
<Border Width="970" Height="530" BorderBrush="#efefef" BorderThickness="2" CornerRadius="5">
<Canvas x:Name="ScrollWrap" Width="970" Height="530" HorizontalAlignment="Center" VerticalAlignment="Center" Background="#f12f3035">
<StackPanel Width="{Binding ElementName=ScrollWrap,Path=ActualWidth}">
<TextBlock Foreground="White" FontSize="20" FontWeight="Bold" Padding="10" HorizontalAlignment="Center" VerticalAlignment="Center">请选择要分享的屏幕或窗口</TextBlock>
</StackPanel>
<ScrollViewer Canvas.Right="0" Canvas.Top="50" Height="480" Width="{Binding ElementName=ScrollWrap,Path=ActualWidth}">
<WrapPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
<StackPanel Width="300" Height="200" Background="GreenYellow" Margin="10"></StackPanel>
</WrapPanel>
</ScrollViewer>
<Button Click="Setting_Btn_Click" Style="{StaticResource CusIconBtn}" Canvas.Right="10" Canvas.Top="0" Background="Transparent" BorderThickness="0">
<Button.Content>
<StackPanel>
<TextBlock FontSize="30" Foreground="#fff" Margin="0 0 0 0">×</TextBlock>
</StackPanel>
</Button.Content>
</Button>
</Canvas>
</Border>
</Grid>
</Canvas>
</Metro:MetroWindow>

View File

@ -12,6 +12,9 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Linq;
using System.Windows.Threading;
using JianGongYun.TRTC.Components;
using System.Runtime.InteropServices;
namespace JianGongYun.TRTC.Windows
{
@ -20,24 +23,38 @@ namespace JianGongYun.TRTC.Windows
/// </summary>
public partial class LiveWindow : MetroWindow
{
[DllImport("Kernel32.dll", EntryPoint = "AttachConsole", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern void AttachConsole(int dwProcessId);
ViewModels.LiveWindowViewModel LiveWindowViewModel;
ViewModels.SettingWindowViewModel SettingWindowViewModel;
public LiveWindow()
{
InitializeComponent();
LiveWindowViewModel =new ViewModels.LiveWindowViewModel();
InitializeComponent();
AttachConsole(-1);
LiveWindowViewModel = new ViewModels.LiveWindowViewModel();
SettingWindowViewModel = ViewModels.SettingWindowViewModel.GetInstance();
this.DataContext = LiveWindowViewModel;
BorderBrush = new SolidColorBrush(color: Color.FromRgb(42, 43, 48));//窗口标题背景颜色
}
private void aaaa(object sender, RoutedEventArgs e)
protected override void OnActivated(EventArgs e)
{
LiveWindowViewModel.StudentCount++;
base.OnActivated(e);
//颜色前台设置无效,手动调用才行
var color = (SolidColorBrush)(new BrushConverter().ConvertFrom("#cccccc"));
Rad1.Foreground = color;
Rad2.Foreground = color;
Rad3.Foreground = color;
Rad4.Foreground = color;
}
private Window settingWindow;
//设置按钮
private void Setting_Btn_Click(object sender, RoutedEventArgs e)
{
var settingWindow = SettingWindow.GetInstance();
settingWindow = SettingWindow.GetInstance();
settingWindow.Closed += (a, b) => settingWindow = null;
settingWindow.Show();
if (settingWindow.WindowState != WindowState.Normal)
{
@ -45,5 +62,124 @@ namespace JianGongYun.TRTC.Windows
}
settingWindow.Topmost = true;
}
protected override void OnClosed(EventArgs e)
{
if (settingWindow != null)
{
settingWindow.Close();
}
base.OnClosed(e);
}
/// <summary>
/// 开始/结束直播
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StartLive_Click(object sender, RoutedEventArgs e)
{
var btn = sender as AduFlatButton;
var start = Convert.ToBoolean(btn.Tag);
if (start)//开始直播
{
this.Dispatcher.Invoke(new Action(() =>
{
btn.Type = AduSkin.Controls.FlatButtonSkinEnum.warning;
btn.Content = "直播倒计时";
}));
StartCountdown(() =>
{
LiveWindowViewModel.IsLive = start;
this.Dispatcher.Invoke(new Action(() =>
{
btn.Type = AduSkin.Controls.FlatButtonSkinEnum.info;
btn.Content = "开始直播";
}));
}, SettingWindowViewModel.ScreenRecordingCountdown);
}
else
{
LiveWindowViewModel.IsLive = start;
}
}
/// <summary>
/// 开始倒计时
/// </summary>
public void StartCountdown(Action countdownEnd, int time = 10)
{
CountdownEnd = countdownEnd;
count = time;
this.Dispatcher.Invoke(new Action(() =>
{
CountdownWrap.Visibility = Visibility.Visible;
}));
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
/// <summary>
/// 倒计时结束执行
/// </summary>
Action CountdownEnd;
/// <summary>
/// 倒计时时间
/// </summary>
private int count;
/// <summary>
/// 创建Timer对象
/// </summary>
private DispatcherTimer timer = null;
private void timer_Tick(object sender, EventArgs e)
{
if (count == 0)
{
timer.Stop();
timer = null;
this.Dispatcher.Invoke(new Action(() =>
{
CountdownWrap.Visibility = Visibility.Hidden;
}));
CountdownEnd?.Invoke();
//count = 10;
//timer.Start();
}
else
{
CountdownControl txt = new CountdownControl(this.CountdownWrap, this);
txt.TxtValue = count.ToString();
txt.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
txt.VerticalAlignment = System.Windows.VerticalAlignment.Center;
this.CountdownWrap.Children.Add(txt);
count--;
}
}
private void Tpye_Click(object sender, RoutedEventArgs e)
{
switch (LiveWindowViewModel.LiveType)
{
case Models.LiveTypeEnum.CameraAndScreen:
break;
case Models.LiveTypeEnum.OnlyScreen:
break;
case Models.LiveTypeEnum.OnlyCamera:
if (!LiveWindowViewModel.CameraRunning)
{
LiveClassroom.StartVideoMain(BeforeLiveViewWrap);
}
break;
case Models.LiveTypeEnum.OnlyAudio:
break;
default:
break;
}
}
}
}

View File

@ -50,11 +50,125 @@
</DockPanel>
</StackPanel>
</Metro:AduGroupBoxNor>
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle2}" Header="录屏设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" Height="380" HeaderPadding="10,6">
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle2}" Header="录屏设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" HeaderPadding="10,6">
<StackPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 视频帧率(fps)</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding ScreenRecordingFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="10" />
<ComboBoxItem Content="12" />
<ComboBoxItem Content="15" />
<ComboBoxItem Content="20" />
<ComboBoxItem Content="24" />
<ComboBoxItem Content="25" />
<ComboBoxItem Content="30" />
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频码率</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=ScreenRecordingAudioBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="24Kbps" Tag="24000" />
<ComboBoxItem Content="32Kbps" Tag="32000"/>
<ComboBoxItem Content="64Kbps" Tag="64000"/>
<ComboBoxItem Content="128Kbps" Tag="128000"/>
<ComboBoxItem Content="192Kbps" Tag="192000"/>
<ComboBoxItem Content="256Kbps" Tag="256000"/>
<ComboBoxItem Content="320Kbps" Tag="320000"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频采样率</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingAudioFreq}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="8000Hz" Tag="8000" />
<ComboBoxItem Content="11025Hz" Tag="11025"/>
<ComboBoxItem Content="16000Hz" Tag="16000"/>
<ComboBoxItem Content="22050Hz" Tag="22050"/>
<ComboBoxItem Content="37800Hz" Tag="37800"/>
<ComboBoxItem Content="44100Hz" Tag="44100"/>
<ComboBoxItem Content="48000Hz" Tag="48000"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 编码级别</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingProfileLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="基本画质" Tag="-profile:v baseline -level 3.0" />
<ComboBoxItem Content="主流画质" Tag="-profile:v main -level 4.2"/>
<ComboBoxItem Content="高级画质" Tag="-profile:v high -level 5.1"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 录制倒计时</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding ScreenRecordingCountdown}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="3s" Tag="3" />
<ComboBoxItem Content="5s" Tag="5"/>
<ComboBoxItem Content="7s" Tag="7"/>
<ComboBoxItem Content="10s" Tag="10"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 保存到文件夹</TextBlock>
<Metro:AduFlatButton CornerRadius="0 3 3 0" Content="打开" x:Name="OpenDir" BorderBrush="#3399ff" BorderThickness="1" Click="OpenDir_Click" Width="50" DockPanel.Dock="Right" Margin="0 0 10 0" Type="info" />
<Metro:AduFlatButton CornerRadius="3 0 0 3" Background="Transparent" BorderBrush="#3399ff" BorderThickness="1" Content="更改" x:Name="ChangeDir" Click="ChangeDir_Click" Width="50" DockPanel.Dock="Right" Margin=" 11 0 0 0" Type="info" />
<Border BorderBrush="White" BorderThickness="1" CornerRadius="3">
<TextBlock Cursor="IBeam" TextTrimming="CharacterEllipsis" ForceCursor="True" ToolTip="{Binding ScreenRecordingDir,Mode=OneWay}" Text="{Binding ScreenRecordingDir,Mode=OneWay}" Foreground="White" Padding="5 7"></TextBlock>
</Border>
</DockPanel>
</StackPanel>
</Metro:AduGroupBoxNor>
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle3}" Header="直播设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" Height="380" HeaderPadding="10,6">
<Metro:AduGroupBoxNor HeaderTemplate="{StaticResource CusHeaderTitle3}" Header="直播设置" HeaderBackground="Transparent" BorderThickness="0" BorderBrush="{StaticResource DefaultBorderBrush}" FontSize="14" HeaderPadding="10,6">
<StackPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 音频质量</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding LiveAudioLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="流畅" Tag="TRTCAudioQualitySpeech" />
<ComboBoxItem Content="高" Tag="TRTCAudioQualityDefault"/>
<ComboBoxItem Content="超高" Tag="TRTCAudioQualityMusic"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面帧率(fps)</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding LiveMainFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="10" />
<ComboBoxItem Content="12" />
<ComboBoxItem Content="15" />
<ComboBoxItem Content="20" />
<ComboBoxItem Content="24" />
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面码率</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveMainBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="1000Kbps" Tag="1000" />
<ComboBoxItem Content="1200Kbps" Tag="1200"/>
<ComboBoxItem Content="1600Kbps" Tag="1600"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 摄像画面级别</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveMainLevel}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="弱网下保流畅" Tag="TRTCVideoQosPreferenceSmooth" />
<ComboBoxItem Content="弱网下保清晰" Tag="TRTCVideoQosPreferenceClear"/>
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 屏幕分享帧率(fps)</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Content" SelectedValue="{Binding LiveSubFps}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="10" />
<ComboBoxItem Content="12" />
<ComboBoxItem Content="15" />
<ComboBoxItem Content="20" />
<ComboBoxItem Content="24" />
</Metro:AduComboBox>
</DockPanel>
<DockPanel Style="{StaticResource SettingItem}">
<TextBlock Style="{StaticResource SettingItemText}" DockPanel.Dock="Left"> 屏幕分享码率</TextBlock>
<Metro:AduComboBox Margin="0 0 10 0" SelectedValuePath="Tag" SelectedValue="{Binding Path=LiveSubBitrate}" ComBoxItemPanelBackground="{StaticResource ComboBoxBrush}">
<ComboBoxItem Content="1200Kbps" Tag="1200"/>
<ComboBoxItem Content="1600Kbps" Tag="1600"/>
<ComboBoxItem Content="2000Kbps" Tag="2000"/>
</Metro:AduComboBox>
</DockPanel>
</StackPanel>
</Metro:AduGroupBoxNor>
</StackPanel>
</Metro:MetroScrollViewer>

View File

@ -1,6 +1,7 @@
using AduSkin.Controls.Metro;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
@ -48,6 +49,10 @@ namespace JianGongYun.TRTC.Windows
this.DataContext = mode;
}
/// <summary>
/// 测试麦克风
/// </summary>
bool micTesting = false;
private void TestMic(object sender, RoutedEventArgs e)
{
@ -87,5 +92,33 @@ namespace JianGongYun.TRTC.Windows
Slider1.DecreaseColor = sliderColor;
Slider2.DecreaseColor = sliderColor;
}
/// <summary>
/// 打开文件浏览器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OpenDir_Click(object sender, RoutedEventArgs e)
{
var process = new Process
{
StartInfo = new ProcessStartInfo { FileName = "explorer.exe", Arguments = mode.ScreenRecordingDir }
};
process.Start();
}
/// <summary>
/// 修改路径
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ChangeDir_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog openFileDialog = new System.Windows.Forms.FolderBrowserDialog(); //选择文件夹
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)//注意此处一定要手动引入System.Window.Forms空间否则你如果使用默认的DialogResult会发现没有OK属性
{
mode.ScreenRecordingDir = openFileDialog.SelectedPath;
}
}
}
}