
En otros artículos he revisado como integrar algunas librerías RTSP para visualización de cámaras en aplicaciones móviles, el día de hoy revisaremos como integrar la librería LibVLCSharp en .Net MAUI que nos ayudará tanto a reproducir el stream de cámara IP como cualquier otro contenido multimedia.
En este proyecto cubriremos lo siguiente:
- Creación del proyecto
- Instalación de la librería
- Creación de un view para reproducir el contenido
- Creación de los handlers para manejar el contenido en Android y iOS
Lo primero que tendremos que hacer es crear un nuevo proyecto en Visual Studio 2022:

Seguidamente tendremos que asignarle un nombre, en mi caso le puse MauiVlc:

Y seguidamente el framework que queremos usar en el proyecto:

Ya una vez cumplido ese paso nuestro proyecto se debe ver de la siguiente manera:

¿Qué tenemos que hacer ahora? Instalar las librerías! para ellos haras click derecho en el proyecto e iras a nuget para buscar la librería VideoLAN.LibVLC.Android y VideoLAN.LibVLC.iOS y si, tienes que instalarlas en el mismo proyecto.
Ya una vez que tenemos las librerías crearemos una carpeta “Controls” en un nuestro proyecto y le agregaremos una clase MediaViewer. El proyecto debería estar viéndose de la siguiente manera:

Y clase MediaViewer debería quedar de la siguiente manera:
public class MediaViewer : View
{
public static BindableProperty VideoUrlProperty = BindableProperty.Create(nameof(VideoUrl)
, typeof(string)
, typeof(MediaViewer)
, ""
, defaultBindingMode: BindingMode.TwoWay);
public string VideoUrl
{
get => (string)GetValue(VideoUrlProperty);
set => SetValue(VideoUrlProperty, value);
}
public MediaViewer()
{
}
}La clase como podrás ver hereda de View e implementa una propiedad VideoUrl para poder indicar la ruta del video que queremos mostrar.
El siguiente paso es crear la carpeta Handlers donde guardaremos los handlers respectivos para el uso de la librería de VLC:

El MediaViewerHandler se verá de la siguiente manera:
public partial class MediaViewerHandler
{
public static IPropertyMapper<MediaViewer, MediaViewerHandler> PropertyMapper =
new PropertyMapper<MediaViewer, MediaViewerHandler>()
{
};
public static CommandMapper<MediaViewer, MediaViewerHandler> CommandMapper = new(ViewCommandMapper)
{
};
public MediaViewerHandler() : base(PropertyMapper, CommandMapper)
{
}
}La implementación para Android se verá así:
public partial class MediaViewerHandler: ViewHandler<MediaViewer, VideoView>
{
VideoView _videoView;
LibVLC _libVLC;
LibVLCSharp.Shared.MediaPlayer _mediaPlayer;
protected override VideoView CreatePlatformView() => new VideoView(Context);
protected override void ConnectHandler(VideoView nativeView)
{
base.ConnectHandler(nativeView);
_libVLC = new LibVLC(enableDebugLogs: true);
_mediaPlayer = new LibVLCSharp.Shared.MediaPlayer(_libVLC)
{
EnableHardwareDecoding = true
};
_videoView = nativeView ?? new VideoView(Context);
_videoView.MediaPlayer = _mediaPlayer;
HandleUrl(VirtualView.VideoUrl);
base.ConnectHandler(nativeView);
}
protected override void DisconnectHandler(VideoView nativeView)
{
nativeView.Dispose();
base.DisconnectHandler(nativeView);
}
private void HandleUrl(string url)
{
try
{
if (url.EndsWith("/"))
{
url = url.TrimEnd('/');
}
//url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
if (!string.IsNullOrEmpty(url))
{
var media = new Media(_libVLC, url, FromType.FromLocation);
_mediaPlayer.NetworkCaching = 1500;
if (_mediaPlayer.Media != null)
{
_mediaPlayer.Stop();
_mediaPlayer.Media.Dispose();
}
_mediaPlayer.Media = media;
_mediaPlayer.Mute = true;
_videoView.MediaPlayer.Play();
}
}
catch (Exception ex)
{
}
}
}public partial class MediaViewerHandler : ViewHandler<MediaViewer, VideoView>
{
VideoView _videoView;
LibVLC _libVLC;
LibVLCSharp.Shared.MediaPlayer _mediaPlayer;
protected override VideoView CreatePlatformView()
{
return new VideoView();
}
protected override void ConnectHandler(VideoView nativeView)
{
base.ConnectHandler(nativeView);
Core.Initialize();
_libVLC = new LibVLC(enableDebugLogs: true);
_mediaPlayer = new LibVLCSharp.Shared.MediaPlayer(_libVLC)
{
EnableHardwareDecoding = true
};
_videoView = nativeView ?? new VideoView();
_videoView.MediaPlayer = _mediaPlayer;
HandleUrl(VirtualView.VideoUrl);
}
protected override void DisconnectHandler(VideoView nativeView)
{
nativeView.Dispose();
base.DisconnectHandler(nativeView);
}
public void HandleUrl(string url)
{
try
{
if (url.EndsWith("/"))
{
url = url.TrimEnd('/');
}
if (!string.IsNullOrEmpty(url))
{
var media = new Media(_libVLC, url, FromType.FromLocation);
_mediaPlayer.NetworkCaching = 1500;
if (_mediaPlayer.Media != null)
{
_mediaPlayer.Stop();
_mediaPlayer.Media.Dispose();
}
_mediaPlayer.Media = media;
_mediaPlayer.Mute = true;
_videoView.MediaPlayer.Play();
}
}
catch (Exception ex)
{
// Handle exception
}
}
}Ya una vez cumplidos esos pasos lo que queda es registrar el handler en el archivo MauiProgram.cs:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureMauiHandlers((handlers) => {
handlers.AddHandler(typeof(MediaViewer), typeof(MauiVlc.Handlers.MediaViewerHandler));
})
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}Si quieres ver el código lo puedes ver en el repositorio de GitHub:
Si quieres ver un ejemplo funcionando puedes descargarte la app de ejemplo aquí:
Android:
ReCam Viewer — Apps on Google Play
Happy Coding!
