1 Star 0 Fork 0

TianYe/FieldTools.MediaFindOut

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
VLCWindow.xaml.cs 32.39 KB
一键复制 编辑 原始数据 按行查看 历史
TianYe 提交于 2024-03-17 03:12 . 项目迁移,基本完善
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
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
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/fieldtianye/field-tools.-media-find-out.git
[email protected]:fieldtianye/field-tools.-media-find-out.git
fieldtianye
field-tools.-media-find-out
FieldTools.MediaFindOut
master

搜索帮助