[CHANGE] Added video info page
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
@inject ISnackbar Snackbar
|
@inject ISnackbar Snackbar
|
||||||
@inject ClientService ClientService
|
@inject ClientService ClientService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
<MudText>Video data</MudText>
|
<MudText>Video data</MudText>
|
||||||
<MudStack Row Spacing="2">
|
<MudStack Row Spacing="2">
|
||||||
|
|||||||
@@ -35,22 +35,6 @@ public partial class DevelopmentVideo : ComponentBase
|
|||||||
Snackbar.Add("Video ID needs to have an length of 11 chars!", Severity.Warning);
|
Snackbar.Add("Video ID needs to have an length of 11 chars!", Severity.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientResult = await ClientService.LoadClientByIdAsync(_selectedClient.Id);
|
NavigationManager.NavigateTo($"/video/{_videoId}?clientId={_selectedClient.Id}");
|
||||||
if (!clientResult.IsSuccess)
|
|
||||||
{
|
|
||||||
Snackbar.Add(clientResult.Error?.Description ?? $"Failed to get client with id: {_selectedClient.Id}", Severity.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ytClient = clientResult.Value;
|
|
||||||
var videoResult = await ytClient.GetVideoByIdAsync(_videoId);
|
|
||||||
if (!videoResult.IsSuccess)
|
|
||||||
{
|
|
||||||
Snackbar.Add(videoResult.Error?.Description ?? $"Failed to load video: {_videoId}", Severity.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ytVideo = videoResult.Value;
|
|
||||||
Snackbar.Add($"Loaded video {ytVideo.Title}", Severity.Success);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
244
Manager.App/Components/Pages/Video.razor
Normal file
244
Manager.App/Components/Pages/Video.razor
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
@page "/Video/{VideoId}"
|
||||||
|
@using Manager.App.Services.System
|
||||||
|
|
||||||
|
@inject ISnackbar Snackbar
|
||||||
|
@inject ClientService ClientService
|
||||||
|
@inject CacheService Cache
|
||||||
|
|
||||||
|
<ForcedLoadingOverlay Visible="_loading"/>
|
||||||
|
@if (!_loading && _video != null)
|
||||||
|
{
|
||||||
|
<MudStack Spacing="2">
|
||||||
|
<MudCard>
|
||||||
|
@{
|
||||||
|
var thumbnailUrl = _video.Thumbnails.OrderByDescending(t => t.Width).FirstOrDefault()?.Url;
|
||||||
|
}
|
||||||
|
@if (!string.IsNullOrWhiteSpace(thumbnailUrl))
|
||||||
|
{
|
||||||
|
<MudCardMedia Image="@Cache.CreateCacheUrl(thumbnailUrl)" Height="500"/>
|
||||||
|
}
|
||||||
|
<MudCardContent>
|
||||||
|
<MudText Typo="Typo.h5">@_video.Title</MudText>
|
||||||
|
<MudText Typo="Typo.body2">@_video.Description</MudText>
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
|
<MudExpansionPanels MultiExpansion>
|
||||||
|
<MudExpansionPanel Text="Info" Expanded>
|
||||||
|
<MudStack Spacing="2" Row Wrap="Wrap.Wrap">
|
||||||
|
@* Info *@
|
||||||
|
<MudSimpleTable Bordered Dense Elevation="0" Outlined Square Hover>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Video ID:</td>
|
||||||
|
<td>@_video.VideoId</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Title:</td>
|
||||||
|
<td>@_video.Title</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description:</td>
|
||||||
|
<td>@_video.Description</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HashTags:</td>
|
||||||
|
<td>@foreach (var hashtag in _video.HashTags)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Variant="Variant.Text" Color="Color.Info">@hashtag</MudChip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>View count:</td>
|
||||||
|
<td>@_video.ViewCount</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Like count:</td>
|
||||||
|
<td>@_video.LikeCount</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Channel ID:</td>
|
||||||
|
<td>@_video.ChannelId</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Author:</td>
|
||||||
|
<td>@_video.Author</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Playability status:</td>
|
||||||
|
<td>@_video.PlayabilityStatus</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Length seconds:</td>
|
||||||
|
<td>@_video.LengthSeconds</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Keywords:</td>
|
||||||
|
<td>@foreach (var keyword in _video.Keywords)
|
||||||
|
{
|
||||||
|
<MudChip T="string" Variant="Variant.Text">@keyword</MudChip>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Publish date:</td>
|
||||||
|
<td>@_video.PublishDate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Upload date:</td>
|
||||||
|
<td>@_video.UploadDate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Category:</td>
|
||||||
|
<td>@_video.Category</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</MudSimpleTable>
|
||||||
|
@* Boolean values *@
|
||||||
|
<MudSimpleTable Bordered Dense Elevation="0" Outlined Square Hover>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Is owner viewing:</td>
|
||||||
|
<td>@_video.IsOwnerViewing</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Allow rating:</td>
|
||||||
|
<td>@_video.AllowRating</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is crawlable:</td>
|
||||||
|
<td>@_video.IsCrawlable</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is private:</td>
|
||||||
|
<td>@_video.IsPrivate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is unplugged corpus:</td>
|
||||||
|
<td>@_video.IsUnpluggedCorpus</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is live:</td>
|
||||||
|
<td>@_video.IsLive</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is family save:</td>
|
||||||
|
<td>@_video.IsFamilySave</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is unlisted:</td>
|
||||||
|
<td>@_video.IsUnlisted</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Has Ypc metadata:</td>
|
||||||
|
<td>@_video.HasYpcMetadata</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Is shorts eligible:</td>
|
||||||
|
<td>@_video.IsShortsEligible</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</MudSimpleTable>
|
||||||
|
</MudStack>
|
||||||
|
</MudExpansionPanel>
|
||||||
|
<MudExpansionPanel Text="Streaming data">
|
||||||
|
@if (_video.StreamingData == null)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Info">No streaming data available!</MudAlert>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudStack Spacing="2" Row Wrap="Wrap.Wrap">
|
||||||
|
<MudStack>
|
||||||
|
<MudText Typo="Typo.h5">Adaptive Formats</MudText>
|
||||||
|
<MudTable Items="@_video.StreamingData.AdaptiveFormats">
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>Id</MudTh>
|
||||||
|
<MudTh>Mime type</MudTh>
|
||||||
|
<MudTh>Bitrate</MudTh>
|
||||||
|
<MudTh>Resolution</MudTh>
|
||||||
|
<MudTh>Last modified (UNIX epoch)</MudTh>
|
||||||
|
<MudTh>Quality</MudTh>
|
||||||
|
<MudTh>FPS</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Itag</MudTd>
|
||||||
|
<MudTd>@context.MimeType</MudTd>
|
||||||
|
<MudTd>@context.Bitrate</MudTd>
|
||||||
|
<MudTd>@($"{context.Width}x{context.Height}")</MudTd>
|
||||||
|
<MudTd>@context.LastModified</MudTd>
|
||||||
|
<MudTd>@context.Quality</MudTd>
|
||||||
|
<MudTd>@context.Fps</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
</MudStack>
|
||||||
|
<MudStack>
|
||||||
|
<MudText Typo="Typo.h5">Formats</MudText>
|
||||||
|
<MudTable Items="@_video.StreamingData.Formats">
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>Id</MudTh>
|
||||||
|
<MudTh>Mime type</MudTh>
|
||||||
|
<MudTh>Bitrate</MudTh>
|
||||||
|
<MudTh>Resolution</MudTh>
|
||||||
|
<MudTh>Last modified (UNIX epoch)</MudTh>
|
||||||
|
<MudTh>Quality</MudTh>
|
||||||
|
<MudTh>FPS</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Itag</MudTd>
|
||||||
|
<MudTd>@context.MimeType</MudTd>
|
||||||
|
<MudTd>@context.Bitrate</MudTd>
|
||||||
|
<MudTd>@($"{context.Width}x{context.Height}")</MudTd>
|
||||||
|
<MudTd>@context.LastModified</MudTd>
|
||||||
|
<MudTd>@context.Quality</MudTd>
|
||||||
|
<MudTd>@context.Fps</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
</MudStack>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
</MudExpansionPanel>
|
||||||
|
<MudExpansionPanel Text="Player config">
|
||||||
|
@if (_video.PlayerConfig == null)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Info">No player config available!</MudAlert>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudSimpleTable Bordered Dense Elevation="0" Outlined Square Hover>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Audio loudness DB:</td>
|
||||||
|
<td>@_video.PlayerConfig.AudioLoudnessDb</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Audio perceptual loudness DB:</td>
|
||||||
|
<td>@_video.PlayerConfig.AudioPerceptualLoudnessDb</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Audio enable per format loudness:</td>
|
||||||
|
<td>@_video.PlayerConfig.AudioLoudnessDb</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Max bitrate:</td>
|
||||||
|
<td>@_video.PlayerConfig.MaxBitrate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Max read ahead time MS:</td>
|
||||||
|
<td>@_video.PlayerConfig.MaxReadAheadMediaTimeMs</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Min read ahead time MS:</td>
|
||||||
|
<td>@_video.PlayerConfig.MinReadAheadMediaTimeMs</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Read ahead growth rate MS:</td>
|
||||||
|
<td>@_video.PlayerConfig.ReadAheadGrowthRateMs</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</MudSimpleTable>
|
||||||
|
}
|
||||||
|
</MudExpansionPanel>
|
||||||
|
</MudExpansionPanels>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
48
Manager.App/Components/Pages/Video.razor.cs
Normal file
48
Manager.App/Components/Pages/Video.razor.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Manager.YouTube.Models;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MudBlazor;
|
||||||
|
|
||||||
|
namespace Manager.App.Components.Pages;
|
||||||
|
|
||||||
|
public partial class Video : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public required string VideoId { get; set; }
|
||||||
|
|
||||||
|
[SupplyParameterFromQuery(Name = "clientId")]
|
||||||
|
public string ClientId { get; set; } = "";
|
||||||
|
|
||||||
|
private bool _loading = true;
|
||||||
|
private YouTubeVideo? _video;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(VideoId))
|
||||||
|
{
|
||||||
|
Snackbar.Add("Video id is null or empty!", Severity.Error);
|
||||||
|
_loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientResult = await ClientService.LoadClientByIdAsync(ClientId);
|
||||||
|
if (!clientResult.IsSuccess)
|
||||||
|
{
|
||||||
|
Snackbar.Add(clientResult.Error?.Description ?? "Failed to load client!", Severity.Error);
|
||||||
|
_loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var client = clientResult.Value;
|
||||||
|
|
||||||
|
var videoResult = await client.GetVideoByIdAsync(VideoId);
|
||||||
|
if (!videoResult.IsSuccess)
|
||||||
|
{
|
||||||
|
Snackbar.Add(videoResult.Error?.Description ?? "Failed to get video.", Severity.Error);
|
||||||
|
_loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_video = videoResult.Value;
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,11 +31,10 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger<ClientServ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void CancellationRequested()
|
private void CancellationRequested()
|
||||||
{
|
{
|
||||||
foreach (var client in _loadedClients)
|
foreach (var client in _loadedClients)
|
||||||
{
|
{
|
||||||
await SaveClientAsync(client);
|
|
||||||
client.Dispose();
|
client.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user