mirror of https://github.com/Squidex/squidex.git
Browse Source
* FFMPEG support * Fix redirects. * Install ffmpeg. * Rebuild options fixed. * Update tests * Catch exception * Disable testpull/1197/head
committed by
GitHub
43 changed files with 407 additions and 174 deletions
@ -0,0 +1,9 @@ |
|||
[*.cs] |
|||
# MA0007: Add a comma after the last value |
|||
dotnet_diagnostic.MA0007.severity = none |
|||
|
|||
# MA0048: File name must match type name |
|||
dotnet_diagnostic.MA0048.severity = none |
|||
|
|||
# SA1633: File must have header |
|||
dotnet_diagnostic.SA1633.severity = none |
|||
@ -0,0 +1,9 @@ |
|||
[*.cs] |
|||
# MA0007: Add a comma after the last value |
|||
dotnet_diagnostic.MA0007.severity = none |
|||
|
|||
# MA0048: File name must match type name |
|||
dotnet_diagnostic.MA0048.severity = none |
|||
|
|||
# SA1633: File must have header |
|||
dotnet_diagnostic.SA1633.severity = none |
|||
@ -0,0 +1,9 @@ |
|||
[*.cs] |
|||
# MA0007: Add a comma after the last value |
|||
dotnet_diagnostic.MA0007.severity = none |
|||
|
|||
# MA0048: File name must match type name |
|||
dotnet_diagnostic.MA0048.severity = none |
|||
|
|||
# SA1633: File must have header |
|||
dotnet_diagnostic.SA1633.severity = none |
|||
@ -0,0 +1,77 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using FFMpegCore; |
|||
using Squidex.Domain.Apps.Core.Assets; |
|||
using Squidex.Domain.Apps.Entities.Assets.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Assets; |
|||
|
|||
public sealed class FFMpegAssetMetadataSource : IAssetMetadataSource |
|||
{ |
|||
public async Task EnhanceAsync(UploadAssetCommand command, |
|||
CancellationToken ct) |
|||
{ |
|||
if (command.Type != AssetType.Unknown) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
var analysis = await FFProbe.AnalyseAsync(command.File.OpenRead(), cancellationToken: ct); |
|||
|
|||
void TryAddInt(string name, long? value) |
|||
{ |
|||
if (value > 0) |
|||
{ |
|||
command.Metadata[name] = value.Value; |
|||
} |
|||
} |
|||
|
|||
void TryAddTimeSpan(string name, TimeSpan value) |
|||
{ |
|||
if (value != TimeSpan.Zero) |
|||
{ |
|||
command.Metadata[name] = value.ToString(); |
|||
} |
|||
} |
|||
|
|||
var audioStream = analysis.AudioStreams.FirstOrDefault(); |
|||
if (audioStream != null) |
|||
{ |
|||
TryAddTimeSpan(KnownMetadataKeys.Duration, audioStream.Duration); |
|||
|
|||
TryAddInt(KnownMetadataKeys.AudioBitrate, audioStream.BitRate / 1000); |
|||
TryAddInt(KnownMetadataKeys.AudioSampleRate, audioStream.SampleRateHz); |
|||
|
|||
command.Type = AssetType.Audio; |
|||
} |
|||
|
|||
var videoStream = analysis.VideoStreams.FirstOrDefault(); |
|||
if (videoStream != null) |
|||
{ |
|||
TryAddTimeSpan(KnownMetadataKeys.Duration, videoStream.Duration); |
|||
|
|||
TryAddInt(KnownMetadataKeys.VideoWidth, videoStream.Width); |
|||
TryAddInt(KnownMetadataKeys.VideoHeight, videoStream.Height); |
|||
|
|||
command.Type = AssetType.Video; |
|||
} |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
// Throws for invalid file types.
|
|||
return; |
|||
} |
|||
} |
|||
|
|||
public IEnumerable<string> Format(Asset asset) |
|||
{ |
|||
yield break; |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Assets; |
|||
using Squidex.Domain.Apps.Core.Assets; |
|||
using Squidex.Domain.Apps.Entities.Assets.Commands; |
|||
using Squidex.Domain.Apps.Entities.TestHelpers; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Assets; |
|||
|
|||
public class FFMpegAssetMetadataSourceTests : GivenContext |
|||
{ |
|||
private readonly FFMpegAssetMetadataSource sut = new FFMpegAssetMetadataSource(); |
|||
|
|||
[Fact] |
|||
public async Task Should_ignore_files_with_type() |
|||
{ |
|||
var command = FakeCommand(AssetType.Image); |
|||
|
|||
await sut.EnhanceAsync(command, default); |
|||
|
|||
Assert.Equal(AssetType.Image, command.Type); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_set_image_height_and_width_metadata_when_file_does_not_have_those_values() |
|||
{ |
|||
var command = Command("SampleAudio_0.4mb.mp3"); |
|||
|
|||
await sut.EnhanceAsync(command, default); |
|||
|
|||
Assert.Null(command.Metadata.GetInt32(KnownMetadataKeys.PixelWidth)); |
|||
Assert.Null(command.Metadata.GetInt32(KnownMetadataKeys.PixelHeight)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_provide_metadata_for_audio() |
|||
{ |
|||
var command = Command("SampleAudio_0.4mb.mp3"); |
|||
|
|||
await sut.EnhanceAsync(command, default); |
|||
|
|||
Assert.Equal(AssetType.Audio, command.Type); |
|||
Assert.Equal(JsonValue.Create(128L), command.Metadata[KnownMetadataKeys.AudioBitrate]); |
|||
Assert.Equal(JsonValue.Create(44100L), command.Metadata[KnownMetadataKeys.AudioSampleRate]); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_provide_metadata_for_broken_video() |
|||
{ |
|||
var command = Command("SampleVideo_Broken.mp4"); |
|||
|
|||
await sut.EnhanceAsync(command, default); |
|||
|
|||
Assert.Equal(AssetType.Video, command.Type); |
|||
Assert.Equal(JsonValue.Create("00:00:11"), command.Metadata[KnownMetadataKeys.Duration]); |
|||
Assert.Equal(JsonValue.Create(317L), command.Metadata[KnownMetadataKeys.AudioBitrate]); |
|||
Assert.Equal(JsonValue.Create(48000L), command.Metadata[KnownMetadataKeys.AudioSampleRate]); |
|||
Assert.Equal(JsonValue.Create(1080L), command.Metadata[KnownMetadataKeys.VideoHeight]); |
|||
Assert.Equal(JsonValue.Create(1920L), command.Metadata[KnownMetadataKeys.VideoWidth]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_format_asset() |
|||
{ |
|||
var source = CreateAsset() with |
|||
{ |
|||
Type = AssetType.Image, |
|||
}; |
|||
|
|||
var formatted = sut.Format(source); |
|||
|
|||
Assert.Empty(formatted); |
|||
} |
|||
|
|||
private static UploadAssetCommand Command(string path) |
|||
{ |
|||
var file = new FileInfo(Path.Combine("Assets", "TestFiles", path)); |
|||
|
|||
return new CreateAsset |
|||
{ |
|||
File = new DelegateAssetFile(file.Name, "mime", file.Length, file.OpenRead), |
|||
}; |
|||
} |
|||
|
|||
private static UploadAssetCommand FakeCommand(AssetType type) |
|||
{ |
|||
return new CreateAsset |
|||
{ |
|||
Type = type, |
|||
}; |
|||
} |
|||
} |
|||
Binary file not shown.
Loading…
Reference in new issue