2508251731

LibVLCsharp 3.94版本保存
This commit is contained in:
jasonchenwork 2025-08-25 17:32:20 +08:00
parent 7b02f47441
commit 91629da1c4
4 changed files with 92 additions and 14 deletions

View File

@ -132,6 +132,7 @@ namespace DualScreenDemo
this.ClientSize = new System.Drawing.Size(1440, 900); this.ClientSize = new System.Drawing.Size(1440, 900);
this.Controls.Add(this.primaryScreenPanel); this.Controls.Add(this.primaryScreenPanel);
this.primaryScreenPanel.Controls.Add(this.videoPanel); this.primaryScreenPanel.Controls.Add(this.videoPanel);
videoPanel.Controls.Add(videoView0);
this.Controls.Add(this.syncCloseButton); this.Controls.Add(this.syncCloseButton);
this.Name = "PrimaryForm"; this.Name = "PrimaryForm";
this.ResumeLayout(false); this.ResumeLayout(false);

View File

@ -11,6 +11,7 @@ using IniParser;
using System.Text; using System.Text;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using LibVLCSharp.WinForms;
namespace DualScreenDemo namespace DualScreenDemo
@ -129,6 +130,8 @@ namespace DualScreenDemo
private List<Label> songLabels = new List<Label>(); private List<Label> songLabels = new List<Label>();
private int _currentPage { get; set; } = 0; private int _currentPage { get; set; } = 0;
private int _totalPages { get; set; } private int _totalPages { get; set; }
public VideoView videoView0 = new VideoView() { Dock = DockStyle.Fill};
public VideoView videoView1 = new VideoView() { Dock = DockStyle.Fill};
// string serverPath = Utils.Env.GetPath("", ""); // string serverPath = Utils.Env.GetPath("", "");
string serverPath = Application.StartupPath; string serverPath = Application.StartupPath;
@ -207,7 +210,7 @@ namespace DualScreenDemo
private Timer autoRefreshTimer; private Timer autoRefreshTimer;
private Timer timerCountdown; private Timer timerCountdown;
string Rtime; string Rtime;
bool test = false; bool test = true;
//private Label pageNumberLabel; // 添加頁碼標籤 //private Label pageNumberLabel; // 添加頁碼標籤
public PrimaryForm() public PrimaryForm()
{ {

View File

@ -3,6 +3,27 @@ using LibVLCSharp.Shared;
namespace DualScreenDemo.Services namespace DualScreenDemo.Services
{ {
public static class ControlExtensions
{
public static Task InvokeAsync(this Control control, Func<Task> func)
{
var tcs = new TaskCompletionSource<object>();
control.BeginInvoke(new Action(async () =>
{
try
{
await func();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}));
return tcs.Task;
}
}
public class MediaService : IDisposable public class MediaService : IDisposable
{ {
private LibVLC _libVLC; private LibVLC _libVLC;
@ -14,17 +35,24 @@ namespace DualScreenDemo.Services
{ {
Core.Initialize(); Core.Initialize();
_libVLC = new LibVLC( _libVLC = new LibVLC(
"--verbose=-1", // "--verbose=-1",
enableDebugLogs: true,
"--audio-time-stretch", "--audio-time-stretch",
"--vout=automatic", "--vout=automatic",
"--h264-fps=30", "--h264-fps=30",
"--aout=directsound", "--aout=directsound",
"--network-caching=300", // "--network-caching=300",
"--file-caching=300", // "--file-caching=300",
"--audio-time-stretch" "--audio-time-stretch"
); );
_libVLC.Log += (sender, args) =>
{
Console.WriteLine($"[{args.Level}] {args.Message}");
};
_mediaPlayer = new MediaPlayer(_libVLC); _mediaPlayer = new MediaPlayer(_libVLC);
_mediaPlayer.AspectRatio = "16:9";
_mediaPlayer.EnableHardwareDecoding = true; _mediaPlayer.EnableHardwareDecoding = true;
} }
@ -59,14 +87,50 @@ namespace DualScreenDemo.Services
return false; return false;
} }
public void LoadMedia(string filePath,int audioTrackIndex = 0) public bool IsAtEndTime()
{
var duration = _mediaPlayer.Media?.Duration ?? 0;
var time = _mediaPlayer.Time;
return duration > 0 && Math.Abs(duration - time) < 1000;
}
private bool _isTransitioning = false;
public void LoadMedia(string filePath, int audioTrackIndex = 0)
{ {
try try
{ {
_mediaPlayer.Stop(); // _mediaPlayer.Stop();
_media?.Dispose(); _media?.Dispose();
_media = new Media(_libVLC, filePath, FromType.FromPath); _media = new Media(_libVLC, filePath, FromType.FromPath);
_mediaPlayer.Media = addMediaOption(_media, audioTrackIndex); _mediaPlayer.Play(addMediaOption(_media, audioTrackIndex));
_mediaPlayer.Stopped += (s, e) => Console.WriteLine("Player Stopped");
// _mediaPlayer.EndReached += async(s, e) =>
// {
// if (_isTransitioning) return;
// _isTransitioning = true;
// try
// {
// await VideoPlayerForm.Instance.InvokeAsync(async () =>
// {
// await VideoPlayerForm.Instance.PlayNextSong();
// await Task.Delay(2000); // Optional delay
// });
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Error during transition: {ex.Message}");
// }
// finally
// {
// _isTransitioning = false;
// }
// };
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -80,6 +144,9 @@ namespace DualScreenDemo.Services
media.AddOption(":avcodec-hw=dxva2"); media.AddOption(":avcodec-hw=dxva2");
media.AddOption($":drop-late-frames"); media.AddOption($":drop-late-frames");
media.AddOption(":audio-output=directsound"); media.AddOption(":audio-output=directsound");
media.AddOption(":network-caching=300");
media.AddOption(":live-caching=300");
media.AddOption(":file-caching=300");
media.AddOption($":audio-track={audioTrackIndex}"); media.AddOption($":audio-track={audioTrackIndex}");
return media; return media;
} }

View File

@ -2,6 +2,7 @@ using System.Runtime.InteropServices;
using DBObj; using DBObj;
using OverlayFormObj; using OverlayFormObj;
using DualScreenDemo.Services; using DualScreenDemo.Services;
using LibVLCSharp.WinForms;
namespace DualScreenDemo namespace DualScreenDemo
{ {
public class VideoPlayerForm : Form public class VideoPlayerForm : Form
@ -69,6 +70,7 @@ namespace DualScreenDemo
private MediaService _mediaService0 = new MediaService(); private MediaService _mediaService0 = new MediaService();
private MediaService _mediaService1 = new MediaService(); private MediaService _mediaService1 = new MediaService();
public static OverlayForm overlayForm; public static OverlayForm overlayForm;
public bool isMuted = false; public bool isMuted = false;
public int previousVolume = 100; public int previousVolume = 100;
@ -120,8 +122,11 @@ namespace DualScreenDemo
} }
else else
{ {
_mediaService0.SetVideoOutput(PrimaryForm.Instance.videoPanel.Handle, PrimaryForm.Instance.videoPanel.Width, PrimaryForm.Instance.videoPanel.Height); // _mediaService0.SetVideoOutput(PrimaryForm.Instance.videoPanel.Handle, PrimaryForm.Instance.videoPanel.Width, PrimaryForm.Instance.videoPanel.Height);
_mediaService1.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height); //_mediaService1.SetVideoOutput(this.Handle, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height);
this.Controls.Add(PrimaryForm.Instance.videoView1);
PrimaryForm.Instance.videoView1.MediaPlayer = _mediaService1.Player;
PrimaryForm.Instance.videoView0.MediaPlayer = _mediaService0.Player;
PlayNextSong(); PlayNextSong();
} }
} }
@ -344,13 +349,15 @@ namespace DualScreenDemo
string pathToPlay = song.getFile(); string pathToPlay = song.getFile();
_mediaService0.LoadMedia(pathToPlay, 0); _mediaService0.LoadMedia(pathToPlay, 0);
_mediaService1.LoadMedia(pathToPlay, song.isPublicSong ? 0 : 1); _mediaService1.LoadMedia(pathToPlay, song.isPublicSong ? 0 : 1);
Play(); // Play();
// Thread.Sleep(100); // Thread.Sleep(100);
PrimaryForm.Instance.muteButton.PerformClick();
PrimaryForm.Instance.muteButton.PerformClick(); // isVocalRemoved = true;
// 音量處理
Mute(isMuted); Mute(isMuted);
// 音量處理
SetVolume(100 + song.getBasic().getDbChange()); SetVolume(100 + song.getBasic().getDbChange());
Task.Run(() => Thread.Sleep(100));
Console.WriteLine(_mediaService1.GetVolume());
if (isSyncToPrimaryMonitor) SyncToPrimaryMonitor(); if (isSyncToPrimaryMonitor) SyncToPrimaryMonitor();
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -396,7 +403,7 @@ namespace DualScreenDemo
{ {
try try
{ {
if (_mediaService1.IsAtEnd()&&_mediaService0.IsAtEnd()) if (_mediaService1.IsAtEndTime())
{ {
BeginInvoke(new Action(async () => BeginInvoke(new Action(async () =>
{ {