From e2a45ab3b3bcdfd58f8baadcb91617de59046b05 Mon Sep 17 00:00:00 2001 From: Foxocube Date: Wed, 1 Jan 2025 17:52:26 +0000 Subject: [PATCH] Implement offline video playback for sonarr and RSS --- .../MediaFeeder/Components/Pages/Video.razor | 2 +- MediaFeeder/MediaFeeder/MediaFeeder.csproj | 1 + .../Providers/DownloadedVideoFrame.razor | 28 ++++++++++++-- .../Providers/DownloadedVideoFrame.razor.cs | 21 +++++++++++ .../MediaFeeder/Providers/VideoFrame.cs | 9 +++++ .../Providers/Youtube/YouTubeVideoFrame.razor | 3 +- .../Youtube/YouTubeVideoFrame.razor.cs | 37 ++++++++++--------- 7 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor.cs create mode 100644 MediaFeeder/MediaFeeder/Providers/VideoFrame.cs diff --git a/MediaFeeder/MediaFeeder/Components/Pages/Video.razor b/MediaFeeder/MediaFeeder/Components/Pages/Video.razor index 7bcff37..d056f91 100644 --- a/MediaFeeder/MediaFeeder/Components/Pages/Video.razor +++ b/MediaFeeder/MediaFeeder/Components/Pages/Video.razor @@ -60,7 +60,7 @@ @if (VideoObject != null && Frame != null) { - + @if (VideoObject.Views > 0) diff --git a/MediaFeeder/MediaFeeder/MediaFeeder.csproj b/MediaFeeder/MediaFeeder/MediaFeeder.csproj index 418b832..a6504a8 100644 --- a/MediaFeeder/MediaFeeder/MediaFeeder.csproj +++ b/MediaFeeder/MediaFeeder/MediaFeeder.csproj @@ -10,6 +10,7 @@ + diff --git a/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor b/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor index fed0602..4d43011 100644 --- a/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor +++ b/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor @@ -1,5 +1,27 @@ +@using Blazored.Video +@using AntDesign +@inherits VideoFrame +

DownloadedVideoFrame

-@code { - -} \ No newline at end of file +@if (Video != null) +{ + @if (Video.DownloadedPath != null) + { + + + + } + else + { +

Video is not downloaded

+ } +} +else +{ + +} diff --git a/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor.cs b/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor.cs new file mode 100644 index 0000000..fd1c6cb --- /dev/null +++ b/MediaFeeder/MediaFeeder/Providers/DownloadedVideoFrame.razor.cs @@ -0,0 +1,21 @@ +using Blazored.Video.Support; + +namespace MediaFeeder.Providers; + +public partial class DownloadedVideoFrame +{ + private void CanPlay(VideoState obj) + { + throw new NotImplementedException(); + } + + private void Ended(VideoState obj) + { + throw new NotImplementedException(); + } + + private void CanPlayThrough(VideoState obj) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/MediaFeeder/MediaFeeder/Providers/VideoFrame.cs b/MediaFeeder/MediaFeeder/Providers/VideoFrame.cs new file mode 100644 index 0000000..a680b25 --- /dev/null +++ b/MediaFeeder/MediaFeeder/Providers/VideoFrame.cs @@ -0,0 +1,9 @@ +using MediaFeeder.Data.db; +using Microsoft.AspNetCore.Components; + +namespace MediaFeeder.Providers; + +public abstract class VideoFrame : ComponentBase +{ + [Parameter] public Video? Video { get; set; } +} diff --git a/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor b/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor index 7337306..c50fefa 100644 --- a/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor +++ b/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor @@ -1,5 +1,6 @@ @inject IJSRuntime JsRuntime @using Microsoft.JSInterop -@implements IDisposable +@implements IAsyncDisposable +@inherits VideoFrame
diff --git a/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor.cs b/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor.cs index 3978b55..01c1146 100644 --- a/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor.cs +++ b/MediaFeeder/MediaFeeder/Providers/Youtube/YouTubeVideoFrame.razor.cs @@ -1,14 +1,13 @@ using System.Text.Json; -using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; namespace MediaFeeder.Providers.Youtube; -public partial class YouTubeVideoFrame +public sealed partial class YouTubeVideoFrame { - [Parameter] public string? VideoId { get; set; } private IJSObjectReference? _youtubeCustomModule; private IJSObjectReference? _youtubeLibraryModule; + private IJSObjectReference? _player; private DotNetObjectReference? _videoFrameRef; protected override async Task OnAfterRenderAsync(bool firstRender) @@ -17,14 +16,17 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { _youtubeLibraryModule = await JsRuntime.InvokeAsync("import", "/iframe_api.js"); _youtubeCustomModule = await JsRuntime.InvokeAsync("import", "./Providers/Youtube/YouTubeVideoFrame.razor.js"); + } + } - Console.WriteLine($"_youtubeLibraryModule: {JsonSerializer.Serialize(_youtubeLibraryModule)}"); - Console.WriteLine($"_youtubeCustomModule: {JsonSerializer.Serialize(_youtubeCustomModule)}"); + protected override async Task OnParametersSetAsync() + { + if (_player == null && Video != null) + { + ArgumentNullException.ThrowIfNull(_youtubeCustomModule); _videoFrameRef ??= DotNetObjectReference.Create(this); - var player = await _youtubeCustomModule.InvokeAsync("initPlayer", _videoFrameRef, VideoId); - - Console.WriteLine($"player: {JsonSerializer.Serialize(player)}"); + _player = await _youtubeCustomModule.InvokeAsync("initPlayer", _videoFrameRef, Video.VideoId); } } @@ -79,30 +81,31 @@ public Task OnApiChange(IJSObjectReference target, JsonElement data) } [JSInvokable] - public Task OnPlayerStateChange(IJSObjectReference target, JsonElement data) + public async Task OnPlayerStateChange(IJSObjectReference target, JsonElement data) { Console.WriteLine($"State change: {JsonSerializer.Serialize(data)}"); - var state = (PlayerState) data.GetInt32(); + var state = (PlayerState) + data.GetInt32(); + if (state == PlayerState.ENDED) { - Console.WriteLine("Video finished!"); // setWatchedStatus(1); + Console.WriteLine("Video finished!"); } else if (state == PlayerState.UNSTARTED) { // player.playVideo(); - target.InvokeVoidAsync("playVideo"); + await target.InvokeVoidAsync("playVideo"); } - - return Task.CompletedTask; } - public void Dispose() + public async ValueTask DisposeAsync() { _videoFrameRef?.Dispose(); - _youtubeLibraryModule?.DisposeAsync(); - _youtubeCustomModule?.DisposeAsync(); + if (_player != null) await _player.DisposeAsync(); + if (_youtubeLibraryModule != null) await _youtubeLibraryModule.DisposeAsync(); + if (_youtubeCustomModule != null) await _youtubeCustomModule.DisposeAsync(); } enum PlayerState