Search code examples
c#wpflibvlcsharp

C# LibVLCSharp issue with playing YouTube


I am trying to play YouTube using the LibVLC on multiple instances, in a WPF app. This works fine maybe 75% of the time, but stream freeze for a second or 2 and get pixeleted the other 25%. This seems to be random.

Here is my code:

public async void PlayUri(string path, bool isMuted, bool repeat)
{
    await Dispatcher.InvokeAsync(new Action(async () =>
    {
        Core.Initialize();

        using (LibVLC libVLC = new LibVLC(MediaOptions(repeat)))
        {
            using (var media = new Media(libVLC, path, FromType.FromLocation))
            {
                await media.Parse(MediaParseOptions.ParseNetwork);
                vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
                if (!repeat)
                    vlcPlayer.EndReached += (sender, args) => ThreadPool.QueueUserWorkItem(_ => waitHandle.Set());
                VideoView.MediaPlayer = vlcPlayer;
                VideoView.MediaPlayer.Play();
            }

            // Set the sound and audio output device            
            SetAudioToDirectsound(isMuted);
        }
    }));            
}

MediaOptions is just passing a string[]

mediaOptions = new[]
{
    "--input-repeat=5",
    "--sout-mux-caching=12000"
};

And (for completeness) SetAudioToDirectSount(bool)

var directsound = VideoView.MediaPlayer.SetAudioOutput("directsound");
IsMuted = isMuted;

This "--sout-mux-caching=12000" option should be caching the next 12 seconds of the video.
Is this correct, and do I need any other options? I look all over the cmd line options and cannot seem to find anything obvious.

Reading at the best practises here, it mentions that
"It is recommended by VLC core developers to only create a single instance of type LibVLC during your application's lifecycle. You may create as many MediaPlayer objects as you want from a single LibVLC object."

In my case it is nested inside a using statement, so I don't seem to be following the best practises. So should I declare:

Core.Initialize();
public LibVLC libVLC {get; set; } = new LibVLC();

only once, and only dispose of the MediaPlayer on unload?


Minimal Testing Solution

New WPF project called VLCStream

NuGet install:

  • VideoLAN.LibVLC.Windows
  • LibVLCSharp.WPF
  • LibVLCSharp

MainWindow.xaml

<Window x:Class="VLCStream.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
        xmlns:local="clr-namespace:VLCStream"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Loaded="Window_Loaded">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Button Content="Play" Click="Button_Click" />

        <vlc:VideoView x:Name="VideoView" Grid.Row="1" />
    </Grid>
</Window>

MainWindow.xaml.cs

using LibVLCSharp.Shared;
using LibVLCSharp.WPF;
using System;
using System.Linq;
using System.Windows;

namespace VLCStream
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Dispatcher.InvokeAsync(new Action(async () =>
            {
                using (LibVLC libVLC = new LibVLC("--sout-mux-caching=12000"))
                {
                    using (var media = new Media(libVLC, "https://youtu.be/pW-iVG0_D34", FromType.FromLocation))
                    {
                        await media.Parse(MediaParseOptions.ParseNetwork);
                        MediaPlayer vlcPlayer = new MediaPlayer(media.SubItems.FirstOrDefault());
                        VideoView.MediaPlayer = vlcPlayer;
                        VideoView.MediaPlayer.Play();
                    }
                }
            }));
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Core.Initialize();
        }
    }
}

Issue seem to be random, more than 1 run needed.


Solution

  • Issue seem to have been linked to the youtube.luac file.
    The file, updated around October 19 2021, seems to work perfectly. Thank you Martin for the assistance.

    A basic project is available here.

    The 3 packages installed are:

    enter image description here

    Before starting, delete the .vs in project folder, as well as the bin and obj folders in the solution.

    Go to here, copy the block of text and then paste it into Notepad. Click File ---> Save As and give it the name youtube.luac Underneath that field change "Text documents" (txt) into All Files via the drop down menu and then click Save.

    Replace the file in the packages folder for both 32 and 64.
    e.g. \packages\VideoLAN.LibVLC.Windows.3.0.16\build\x64\lua\playlist

    Rebuild your project, and voila.
    That solved it for me, and as little documentation is available, hopefully this will help someone.. :)