代码拉取完成,页面将自动刷新
using FieldTools.MediaFindOut.Control;
using LibVLCSharp.Shared;
using MediaInfo;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace FieldTools.MediaFindOut
{
/// <summary>
/// VLCWindow.xaml 的交互逻辑,暂时只处理本地路径,后续有时间再处理网络路径。vlc兼容性可能比较强,但问题也是最多,暂时封住,就这样了,越写bug越多,有时间用FFmpeg重写
/// <![CDATA[2024/03/09]]>
/// </summary>
public partial class VLCWindow : Window
{
#region 初始化
static ILogger<VLCWindow> logger = new NullLogger<VLCWindow>();
/// <summary>
/// 默认构建
/// </summary>
public VLCWindow()
{
InitializeComponent();
InIt();
}
/// <summary>
/// 使用MediaInfoWrapper构建
/// </summary>
/// <param name="mediaInfos"></param>
public VLCWindow(List<MediaInfoWrapper> mediaInfos)
{
InitializeComponent();
MediaInfos = mediaInfos;
InIt();
}
/// <summary>
/// 使用地址集合构建
/// </summary>
/// <param name="urls"></param>
public VLCWindow(List<string> urls)
{
InitializeComponent();
MediaInfos = [];
foreach (var item in urls)
{
MediaInfos.Add(new MediaInfoWrapper(item, logger));
}
InIt();
}
/// <summary>
/// 预置数据初始化
/// </summary>
private void InIt()
{
FastForwardTime = 5000;
FastReverseTime = 5000;
UrlIndex = 0;
ListWidth = 150;
foreach (var item in MediaInfos)
{
var path = GetPathFromMediaInfoWrapper(item);
if (string.IsNullOrEmpty(path)) continue;
var name = Path.GetFileName(path);
MediaUrls.Add(new(name, path));
}
if (int.TryParse(ConfigHelper.ReadSetting(nameof(PlayAfterTag)), out int tag))
PlayAfterTag = tag;
else
PlayAfterTag = 1;
this.DataContext = this;
this.Loaded += VLCWindow_Loaded;
this.Closed += VLCWindow_Closed;
}
#endregion
#region 实体
//readonly static LibVLC libvlc = new([]);
//static readonly MediaPlayer player = new(libvlc);
LibVLC? libvlc;
MediaPlayer? player;
Media? media;
/// <summary>
/// 快进时间
/// </summary>
private long FastForwardTime = 5000;
/// <summary>
/// 快退时间
/// </summary>
private long FastReverseTime = 5000;
/// <summary>
/// 播放列表
/// </summary>
public List<KeyValuePair<string, string>> MediaUrls { get; set; } = [];
/// <summary>
/// 列表宽度
/// </summary>
public double ListWidth { get; set; } = 150;
/// <summary>
/// 媒体信息集合。MediaInfoWrapper的构造有bug,对于logger写的是可传入为空,但看源码的话实际却没考虑空的情况(比如赋有效的默认值之类的),直接就调用了,必须要传才行,否者会报空引用错误
/// </summary>
public List<MediaInfoWrapper> MediaInfos { get; set; } = [
new("./Assets/Videos/m1.mp4", logger),
new("./Assets/Videos/m2.mp4", logger),
new("./Assets/Videos/m3.mp4", logger)
];
private int urlIndex = 0;
/// <summary>
/// 列表索引号
/// </summary>
public int UrlIndex
{
get { return urlIndex; }
set
{
urlIndex = (value >= MediaUrls.Count) ? 0 : (value < 0 ? MediaUrls.Count - 1 : value);
}
}
/// <summary>
/// 列表是否展开
/// </summary>
public bool IsListEx { get; set; } = true;
/// <summary>
/// 播放后的行为集合
/// </summary>
public static List<KeyValuePair<string, int>> PlayAfterTags => [new("停止", 1), new("重播", 2), new("下一曲", 3)];
/// <summary>
/// 播放后的行为,1停止,2重播,3下一曲
/// </summary>
public int PlayAfterTag
{
get { return (int)GetValue(PlayAfterTagProperty); }
set
{
SetValue(PlayAfterTagProperty, value);
ConfigHelper.AddUpdateAppSettings(nameof(PlayAfterTag), value.ToString());
}
}
/// <summary>
/// Using a DependencyProperty as the backing store for PlayAfterTag. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty PlayAfterTagProperty =
DependencyProperty.Register("PlayAfterTag", typeof(int), typeof(VLCWindow), new PropertyMetadata(1));
#endregion
#region 事件
/// <summary>
/// 界面关闭,释放资源
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void VLCWindow_Closed(object? sender, EventArgs e)
{
media?.Dispose();
player?.Dispose();
libvlc?.Dispose();
}
/// <summary>
/// 界面加载完成
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void VLCWindow_Loaded(object sender, RoutedEventArgs e)
{
//播放器初始化
libvlc = new LibVLC();
player = new MediaPlayer(libvlc);
//video_main.Width = this.Width;
//video_main.Height = this.Height;
video_main.MediaPlayer = player;
//通过设置宽高比为窗体宽高可达到视频铺满全屏的效果
//player.AspectRatio = this.Width + ":" + this.Height;
//基础数据初始化
showGrid.Visibility = Visibility.Collapsed;
SetLocalMedia();
listBox.SelectedIndex = UrlIndex;
textBlockVideoContent.Text = MediaInfos[UrlIndex].Text;
//播放器事件绑定
player.TimeChanged += Player_TimeChanged;
player.Playing += MediaPlayer_Playing;
player.Paused += Player_Paused;
player.EndReached += Player_EndReached;
}
/// <summary>
/// 播放结束后
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Player_EndReached(object? sender, EventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
//停止
if (PlayAfterTag == 1)
{
//播放按钮状态
playButton.Visibility = Visibility.Visible;
pauseButton.Visibility = Visibility.Collapsed;
//进度条校正
slider.Value = slider.Maximum;
}
}));
//libvlc不能调用自己,否则会死锁……这里让另外的线程来调用……
//参考:https://stackoverflow.com/questions/56487740
//https://github.com/ZeBobo5/Vlc.DotNet/wiki/Vlc.DotNet-freezes-(don't-call-Vlc.DotNet-from-a-Vlc.DotNet-callback)
ThreadPool.QueueUserWorkItem((o) =>
{
Dispatcher.Invoke(new Action(() =>
{
//重播
if (PlayAfterTag == 2)
{
SetLocalMedia();
}
//下一曲
else if (PlayAfterTag == 3)
{
SetNextLocalMedia();
}
}));
});
}
/// <summary>
/// 播放器暂停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Player_Paused(object? sender, EventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
playButton.Visibility = Visibility.Visible;
pauseButton.Visibility = Visibility.Collapsed;
}));
}
/// <summary>
/// 播放器正在播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MediaPlayer_Playing(object? sender, EventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
playButton.Visibility = Visibility.Collapsed;
pauseButton.Visibility = Visibility.Visible;
}));
}
/// <summary>
/// 播放器时间改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Player_TimeChanged(object? sender, MediaPlayerTimeChangedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (media != null)
{
slider.Maximum = media.Duration;
slider.Value = e.Time;
timeShow.Text = GetFormatTime(e.Time) + "/" + GetFormatTime(media.Duration);
}
}));
}
/// <summary>
/// 截图
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Snapshot_Click(object sender, RoutedEventArgs e)
{
string dirPath = AppDomain.CurrentDomain.BaseDirectory + "snapshot\\";
if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); }
//string dirPath = "D:\\A\\";
string imgName = DateTime.Now.Ticks + ".png";
string filePath = dirPath + imgName;
if (player != null && player.TakeSnapshot(0, filePath, (uint)this.video_main.Width, (uint)this.video_main.Height))
{
MessageManage.Success("已成功截图,文件路径为:" + filePath);
}
}
/// <summary>
/// 进度条值改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Dispatcher.Invoke(new Action(() =>
{
//不可去操作播放器时间,防止循环调用
//todo显示预览图
}));
}
/// <summary>
/// 进度条点击/拖动按下,需要暂停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Slider_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (player != null && player.WillPlay)
{
if (player.IsPlaying)
{
player.SetPause(true);
}
}
}));
}
/// <summary>
/// 进度条拖动抬起
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Slider_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (player != null && player.WillPlay)
{
var newValue = slider.Value;
player.Time = (long)newValue;
if (!player.IsPlaying)
{
player.SetPause(false);
}
}
//播放结束后拖动进度条需要重新载入播放
else
{
var time = (long)slider.Value;
SetLocalMedia();
if (player != null) player.Time = time;
}
}));
}
/// <summary>
/// 播放/暂停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click(object sender, RoutedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (player != null && player.WillPlay)
{
if (player.IsPlaying)
{
player.SetPause(true);
}
else
{
player.SetPause(false);
}
}
else
{
SetLocalMedia();
}
}));
}
/// <summary>
/// 快退
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_FastReverse_Click(object sender, RoutedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (player != null && player.IsPlaying)
player.Time -= player.Time < FastReverseTime ? player.Time : FastReverseTime;
}));
}
/// <summary>
/// 快进
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_FastForward_Click(object sender, RoutedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
if (player != null && player.IsPlaying)
player.Time += player.Length - player.Time < FastForwardTime ? player.Length - player.Time : FastForwardTime;
}));
}
/// <summary>
/// 上一个文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Previous_One_Click(object sender, RoutedEventArgs e) => SetPrevLocalMedia();
/// <summary>
/// 下一个文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Next_One_Click(object sender, RoutedEventArgs e) => SetNextLocalMedia();
/// <summary>
/// 重新播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Refresh_Click(object sender, RoutedEventArgs e) => SetLocalMedia();
/// <summary>
/// 列表展开/折叠
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_List_Click(object sender, RoutedEventArgs e)
{
if (IsListEx || this.WindowState == WindowState.Maximized)
{
//记录折叠前的宽度,以便恢复的时候,还是旧值
ListWidth = columnDefinitionEx.Width.Value == 0 ? ListWidth : columnDefinitionEx.Width.Value;
columnDefinitionEx.Width = new GridLength(0);
IsListEx = false;
}
else
{
columnDefinitionEx.Width = new GridLength(ListWidth);
IsListEx = true;
}
}
/// <summary>
/// 全屏切换
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_FullScreen_Click(object sender, RoutedEventArgs e)
{
if (WindowState == WindowState.Normal)
{
WindowState = WindowState.Maximized;
}
else if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
Dispatcher.Invoke(new Action(() =>
{
if (player != null)
{
player.ToggleFullscreen();
if (player.Fullscreen)
{
canceFullScreenIconButton.Visibility = Visibility.Visible;
fullScreenIconButton.Visibility = Visibility.Collapsed;
Button_List_Click(sender, e);
}
else
{
canceFullScreenIconButton.Visibility = Visibility.Collapsed;
fullScreenIconButton.Visibility = Visibility.Visible;
Button_List_Click(sender, e);
}
}
}));
}
/// <summary>
/// 列表选项切换
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ListBox listBox)
{
UrlIndex = listBox.SelectedIndex;
SetLocalMedia();
}
}
/// <summary>
/// 鼠标移入或移开出Grid,控制操作区显示和隐藏
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_MouseEnterOrLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
if (showGrid.Visibility == Visibility.Collapsed)
showGrid.Visibility = Visibility.Visible;
else if (showGrid.Visibility == Visibility.Visible)
showGrid.Visibility = Visibility.Collapsed;
else showGrid.Visibility = Visibility.Visible;
}
/// <summary>
/// 滚轮滚动,缩放画面。缩放有异常,后续再修,暂时不采用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Video_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
//取一次缩放0.1
var delta = e.Delta > 0 ? 0.1f : -0.1f;
if (player?.Scale + delta <= 0 || player?.Scale + delta > 10) return;
if (player != null) player.Scale += delta;
AddLineLog("缩放比例设置为:" + player?.Scale);
}
/// <summary>
/// 信息按钮点击
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Info_Click(object sender, RoutedEventArgs e)
{
if (borderVideoContent.Visibility == Visibility.Collapsed || borderVideoContent.Visibility == Visibility.Hidden)
{
borderVideoContent.Visibility = Visibility.Visible;
}
else
{
borderVideoContent.Visibility = Visibility.Collapsed;
}
}
/// <summary>
/// 拖动窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Win_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.DragMove();
}
/// <summary>
/// 关闭
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
/// <summary>
/// 最小化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Min_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
/// <summary>
/// 最大化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Max_Click(object sender, RoutedEventArgs e)
{
if (this.WindowState == WindowState.Maximized)
{
this.WindowState = WindowState.Normal;
Button_List_Click(sender, e);
}
else
{
this.WindowState = WindowState.Maximized;
Button_List_Click(sender, e);
}
Dispatcher.Invoke(new Action(() =>
{
player?.ToggleFullscreen();
}));
}
/// <summary>
/// 打开/关闭播放设置界面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SettingButton_Click(object sender, RoutedEventArgs e)
{
settingPopup.IsOpen = !settingPopup.IsOpen;
}
/// <summary>
/// combobox被选中,依赖属性的绑定有问题,要单独处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ComboBox_Selected(object sender, SelectionChangedEventArgs e)
{
if (sender is ComboBox box)
{
PlayAfterTag = (int)box.SelectedValue;
}
}
#endregion
#region 方法
/// <summary>
/// 打印一行日志
/// </summary>
/// <param name="str"></param>
private void AddLineLog(string str)
{
var ss = DateTime.Now.ToString();
Dispatcher.Invoke(new Action(() =>
{
logTextBlock.Text = "[" + ss + "]" + str + "(3秒后自动清除)";
}));
Dispatcher.Invoke(new Action(async () =>
{
await Task.Delay(3000);
logTextBlock.Text = "无";
}));
}
/// <summary>
/// 从MediaInfoWrapper中获取_filePath
/// </summary>
/// <param name="mediaInfo"></param>
/// <returns></returns>
private static string? GetPathFromMediaInfoWrapper(MediaInfoWrapper mediaInfo)
{
if (mediaInfo == null) return null;
//这个库让人有点无语,文件地址应该还是比较常用的,但实体对象中没有文件地址,让人有点恼火,为了方便,用反射来拿私有的字段了.
//当然,Text字段中也能提取到文件地址
return mediaInfo.GetType().GetField("_filePath", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(mediaInfo)?.ToString();
}
/// <summary>
/// 将MediaInfoWrapper.Text转为字典,以方便提取展示
/// </summary>
/// <param name="mediaInfo"></param>
/// <returns></returns>
private static Dictionary<string, string> GetDicFromMediaInfoWrapperText(MediaInfoWrapper mediaInfo)
{
if (mediaInfo == null) return [];
var ts = mediaInfo.Text.Split("\r\n");
var ds = new Dictionary<string, string>();
foreach (var t in ts)
{
if (t.Contains(':'))
{
var keyValue = t.Split(':');
if (keyValue.Length == 2)
{
ds.Add(keyValue[0].TrimEnd(), keyValue[1]);
}
}
}
return ds;
}
/// <summary>
/// 提取MediaInfoWrapper.Text中指定字段,示例对应关系如下(21.9.3.0版本):
/// <para> General </para>
/// <para> Complete name : F:\Project\Assets\Videos\m3.mp4 </para>
/// <para> Format : MPEG-4 </para>
/// <para> Format profile : Base Media </para>
/// <para> Codec ID : isom(isom/iso2/mp41) </para>
/// <para> File size : 1.83 MiB </para>
/// <para> Duration : 37 s 245 ms </para>
/// <para> Overall bit rate : 412 kb/s </para>
/// <para> Description : Packed by Bilibili XCoder v2.0.2 </para>
/// <para> Writing application : Lavf60.16.100 </para>
/// <para> </para>
/// <para> Video </para>
/// <para> ID : 1 </para>
/// <para> Format : HEVC </para>
/// <para> Format/Info : High Efficiency Video Coding </para>
/// <para> Format profile : Main @L4@Main </para>
/// <para> Codec ID : hev1 </para>
/// <para> Codec ID/Info : High Efficiency Video Coding </para>
/// <para> Duration : 37 s 201 ms </para>
/// <para> Source duration : 37 s 199 ms </para>
/// <para> Bit rate : 242 kb/s </para>
/// <para> Width : 854 pixels </para>
/// <para> Height : 426 pixels </para>
/// <para> Display aspect ratio : 2.001 </para>
/// <para> Original display aspect ratio : 2.000 </para>
/// <para> Frame rate mode : Variable </para>
/// <para> Frame rate : 30.000 FPS </para>
/// <para> Minimum frame rate : 29.412 FPS </para>
/// <para> Maximum frame rate : 30.303 FPS </para>
/// <para> Color space : YUV </para>
/// <para> Chroma subsampling : 4:2:0 </para>
/// <para> Bit depth : 8 bits </para>
/// <para> Bits/(Pixel* Frame) : 0.022 </para>
/// <para> Stream size : 1.08 MiB(59%) </para>
/// <para> Source stream size : 1.08 MiB(59%) </para>
/// <para> Color range : Limited </para>
/// <para> Color primaries : BT.709 </para>
/// <para> Transfer characteristics : BT.709 </para>
/// <para> Matrix coefficients : BT.709 </para>
/// <para> mdhd_Duration : 37200 </para>
/// <para> Codec configuration box : hvcC </para>
/// <para> </para>
/// <para> Audio </para>
/// <para> ID : 2 </para>
/// <para> Format : AAC LC </para>
/// <para> Format/Info : Advanced Audio Codec Low Complexity </para>
/// <para> Codec ID : mp4a-40-2 </para>
/// <para> Duration : 37 s 245 ms </para>
/// <para> Bit rate mode : Constant </para>
/// <para> Bit rate : 159 kb/s </para>
/// <para> Channel(s) : 2 channels </para>
/// <para> Channel layout : L R </para>
/// <para> Sampling rate : 44.1 kHz </para>
/// <para> Frame rate : 43.066 FPS(1024 SPF) </para>
/// <para> Compression mode : Lossy </para>
/// <para> Stream size : 725 KiB(39%) </para>
/// <para> Default : Yes </para>
/// <para> Alternate group : 1 </para>
/// </summary>
/// <param name="mediaInfo"></param>
/// <param name="key"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private static string GetValueFromMediaInfoWrapperText(MediaInfoWrapper mediaInfo, string key)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentException($"“{nameof(key)}”不能为 null 或空。", nameof(key));
}
var ds = GetDicFromMediaInfoWrapperText(mediaInfo);
return ds[key];
}
/// <summary>
/// 设置本地播放媒体,使用MediaInfoWrapper
/// </summary>
/// <param name="mediaInfoWrapper"></param>
private void SetLocalMedia(MediaInfoWrapper mediaInfoWrapper)
{
var url = GetPathFromMediaInfoWrapper(mediaInfoWrapper);
if (string.IsNullOrEmpty(url)) return;
SetLocalMedia(url);
}
/// <summary>
/// 设置本地播放媒体,默认使用当前播放序列号
/// </summary>
private void SetLocalMedia()
{
SetLocalMedia(MediaUrls[UrlIndex].Value);
}
/// <summary>
/// 播放下一个
/// </summary>
private void SetNextLocalMedia()
{
UrlIndex++;
listBox.SelectedIndex = UrlIndex;
SetLocalMedia();
}
/// <summary>
/// 播放上一个
/// </summary>
private void SetPrevLocalMedia()
{
UrlIndex--;
listBox.SelectedIndex = UrlIndex;
SetLocalMedia();
}
/// <summary>
/// 设置本地播放媒体,使用url
/// </summary>
/// <param name="url"></param>
private void SetLocalMedia(string url)
{
url = Path.GetFullPath(url);
if (!string.IsNullOrEmpty(url) && libvlc != null && player != null)
{
media?.Dispose();
//player.Media?.Dispose();
media = new Media(libvlc, new Uri(url));
//media = new Media(libvlc, new Uri(url), options: [":repeat", ":no-audio"]);
//media?.AddOption(":rotate-angle=<90>");
//media?.AddOption(":no-audio");
//media?.AddOption(":repeat");
//player.Dispose();
//player = new(libvlc);
//video_main.MediaPlayer = player;
//设置初始缩放比例(单向满屏效果)
#region 异常代码,待后续研究
//uint width = 0;
//uint height = 0;
//int width1 = 0;
//int height1 = 0;
//获取播放器的高度宽度,无法获取,一直都失败
//var re = player?.Size(0, ref width, ref height);//返回false
//var r2 = player?.Cursor(0, ref width1, ref height1);//返回false
//设置缩放比例,无法正常匹配,会乱
//MediaInfoWrapper的构造有bug,对于logger写的是可传入为空,但实际却没考虑空的情况,源码中直接就调用了,实际使用时必须要传实体才行,否者会报空引用错误
//var mediaInfo = new MediaInfoWrapper(url, logger);
//if (player.WillPlay)
//{
// player.Scale = mediaInfo.Width / (this.Width - (IsListEx ? ListWidth : 0)) > mediaInfo.Height / (this.Height - CaptionHeigth) ?
// (float)((this.Width - (IsListEx ? ListWidth :0)) / mediaInfo.Width) : //以宽度为基准
// (float)((this.Height - CaptionHeigth) / mediaInfo.Height);//以高度为基准
//}
//AddLineLog("缩放比例设置为:" + player.Scale);
#endregion
player.Play(media);
//设置进度条
slider.Maximum = media.Duration;
//player.Scale = player.Scale;
}
}
/// <summary>
/// 获取指定格式时间
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
static private string GetFormatTime(long time)
{
TimeSpan timeSpan = TimeSpan.FromMilliseconds(time);
return $"{timeSpan.Days:00}:{timeSpan.Hours:00}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}:{timeSpan.Milliseconds:000}";
}
#endregion
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。