Rudimentary Video Player Example
jinyus opened this issue · 9 comments
Hey, I quite new to fsharp and dotnet as a whole and I'd like to build a media manager with fabulous and wondering if video playback is even possible based on upstream issues: AvaloniaUI/Avalonia#2571
I see a simple sample with LibVLCSharp at https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/samples/LibVLCSharp.FSharp.Sample/Program.fs?ref_type=heads
but I am not sure how to wire it up with fabulous...is it possible to provide an example on how to use libVLCSharp with fabulous?
Hi @jinyus !
Which platforms are you targeting? iOS, Android, Windows?
I see the Avalonia issue and the LibVLC sample code you shared are both targeting Windows only.
First thing you'll need is a media player control that works with Avalonia if you are using Fabulous.Avalonia.
My main target is linux, I plan to support windows and macos at a later date. Thanks for pointing me in the right direction.
Seems like this package would work on Linux, Windows and macOS: https://www.nuget.org/packages/LibVLCSharp.Avalonia
They provide a VideoView
control you can add to your interface.
To be able to use the VideoView
control in Fabulous, you'll need to create a widget that will wrap this control.
// Tells Fabulous that VideoView inherits all the same modifiers than Control
// eg. BackgroundColor, Width, Height, etc.
type IFabVideoView = inherit IFabControl
module VideoView =
// Register the new widget with Fabulous
// This tells Fabulous that if you use the this VideoView widget, it needs to instantiate a LibVLCSharp.Avalonia.VideoView control
let WidgetKey = Widgets.register<LibVLCSharp.Avalonia.VideoView>()
// Declare the properties you will set on the widget
// Here VideoView has only one: MediaPlayer
let MediaPlayer = Attributes.defineAvaloniaPropertyWithEquality VideoView.MediaPlayerProperty
// Define the available constructors for the widget we are creating
// Here VideoView only makes sense if we provide the MediaPlayer so let's make it mandatory in the constructor
[<AutoOpen>]
module VideoViewBuilders =
type Fabulous.Avalonia.View with
static member inline VideoView<'msg>(mediaPlayer: MediaPlayer) =
WidgetBuilder<'msg, IFabVideoView>(
VideoView.WidgetKey,
VideoView.MediaPlayer.WithValue(mediaPlayer)
)
That's it. Now you can use this new VideoView
widget in your Fabulous.Avalonia project.
module App =
// Initialize the media player with the media source
// Note that all objects are disposable but here for brevity I don't dispose them
let mediaPlayer =
let libVLC = new LibVLC()
let media = new Media(libVLC, new Uri(@"C:\tmp\big_buck_bunny.mp4"))
new MediaPlayer(media)
type Model =
{ IsPlaying: bool }
type Msg =
| Play
| Stop
let init () = { IsPlaying = false }
let update msg model =
match msg with
| Play ->
mediaPlayer.Play()
{ model with IsPlaying = true }
| Stop ->
mediaPlayer.Stop()
{ model with IsPlaying = false }
let view model =
VStack() {
Button("Play", Play)
Button("Stop", Stop)
VideoView(mediaPlayer)
}
Did you get this to build? Just installing LibVLCSharp.Avalonia makes the demo template unbuildable with this error:
FSC : error FS0193: The module/namespace 'Avalonia.Input.GestureRecognizers' from compilation
unit 'Avalonia.Base' did not contain the namespace, module or type 'IGestureRecognizer'
edit:
I installed v3.7.0 and it builds now. I'm guessing there was a breaking change and Avalonia doesn't follow semver.
In another stalemate, it looks like LibVLCSharp.Avalonia 3.7.0 doesn't support Avalonia 11 but 3.8.1 fails to build with the stacktrace in the video:
stacktrace
FSC : error FS0193: The module/namespace 'Avalonia.Input.GestureRecognizers' from compilation unit 'Avalonia.Base' did not contain the namespace, module or type 'IGestureRecognizer' [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/player.fs(15,21): error FS0039: The value, namespace, type or module 'Widgets' is not defined. Maybe you want one of the following: Widget WidgetKey WidgetDiff WidgetChanges WidgetChange [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/player.fs(19,34): error FS0039: The value, constructor, namespace or type 'defineAvaloniaPropertyWithEquality' is not defined. Maybe you want one of the following: defineSimpleScalarWithEquality [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/player.fs(31,17): error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/player.fs(29,13): error FS0041: A unique overload for method 'WidgetBuilder`2' could not be determined based on type information prior to this program point. A type annotation may be needed.Known types of arguments: 'a * 'bCandidates: - new: key: WidgetKey * attributes: AttributesBundle -> WidgetBuilder<'msg,'marker> - new: key: WidgetKey * scalar: ScalarAttribute -> WidgetBuilder<'msg,'marker> [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
FSC : error FS0193: The module/namespace 'Avalonia.Input.GestureRecognizers' from compilation unit 'Avalonia.Base' did not contain the namespace, module or type 'IGestureRecognizer' [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/App.fs(31,13): warning FS3560: This copy-and-update record expression changes all fields of record type 'demo.App.Model'. Consider using the record construction syntax instead. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/App.fs(35,13): warning FS3560: This copy-and-update record expression changes all fields of record type 'demo.App.Model'. Consider using the record construction syntax instead. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/App.fs(38,9): error FS0039: The value or constructor 'VStack' is not defined. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/App.fs(45,21): error FS0039: The value or constructor 'DesktopApplication' is not defined. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/App.fs(48,27): error FS0039: The type 'Program<_,_,_,_>' does not define the field, constructor or member 'statefulWithCmd'. [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
FSC : error FS0193: The module/namespace 'Avalonia.Input.GestureRecognizers' from compilation unit 'Avalonia.Base' did not contain the namespace, module or type 'IGestureRecognizer' [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
/home/dev/projects/fs/demo/Platform/Desktop/Program.fs(14,34): error FS0039: The value, namespace, type or module 'Program' is not defined. Maybe you want one of the following: Progress [/home/dev/projects/fs/demo/demo.fsproj::TargetFramework=net7.0]
The build failed. Fix the build errors and run again.
Here's the repo if you want to take a look: https://github.com/jinyus/fabulous_video_player_demo
@edgarfgp Could this be a breaking change in Avalonia between the preview versions and the latest stable one?
Fabulous.Avalonia 2.0.0-pre9
is built against Avalonia 11.0.0-preview8
.
LibVLCSharp.Avalonia 3.8.1
is built against 11.0.4
Ah, just noticed there is a Fabulous.Avalonia version 2.0.0-pre14
that is more recent but NuGet considers it a lower version...
https://www.nuget.org/packages/Fabulous.Avalonia/2.0.0-pre14
This should work better
@jinyus Opened a PR to attempt making it run on Linux: jinyus/fabulous_video_player_demo#1
Thanks for the assistance, your PR solved all issues. I will close this issue now.