Skip to content

Commit

Permalink
fix: Snapshots from rotated videos should have correct width/height
Browse files Browse the repository at this point in the history
Some video-files have their metadata as -90 instead of 90. This PR handles correct aspect-ratio and rotation when taking snapshots.

The sample video provided in the PR is my own recording. A bit too big maybe? I couldn't find any command to set the metadata to `-90` on existing video. Would be happy to get it working on already existing test-data to reduce size.

Fixes #509
  • Loading branch information
Hagfjall committed Mar 30, 2024
1 parent eb221c3 commit 82cc971
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 1 deletion.
3 changes: 3 additions & 0 deletions FFMpegCore.Test/FFMpegCore.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
<None Update="Resources\input_3sec_rotation_90deg.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_3sec_rotation_negative_90deg.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_audio_only_10sec.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
7 changes: 7 additions & 0 deletions FFMpegCore.Test/FFProbeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ public void Probe_Rotation()
Assert.AreEqual(90, info.PrimaryVideoStream.Rotation);
}

[TestMethod]
public void Probe_Rotation_Negative_Value()
{
var info = FFProbe.Analyse(TestResources.Mp4VideoRotationNegative);
Assert.AreEqual(-90, info.PrimaryVideoStream.Rotation);
}

[TestMethod, Timeout(10000)]
public async Task Probe_Async_Success()
{
Expand Down
1 change: 1 addition & 0 deletions FFMpegCore.Test/Resources/TestResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public static class TestResources
{
public static readonly string Mp4Video = "./Resources/input_3sec.mp4";
public static readonly string Mp4VideoRotation = "./Resources/input_3sec_rotation_90deg.mp4";
public static readonly string Mp4VideoRotationNegative = "./Resources/input_3sec_rotation_negative_90deg.mp4";
public static readonly string WebmVideo = "./Resources/input_3sec.webm";
public static readonly string Mp4WithoutVideo = "./Resources/input_audio_only_10sec.mp4";
public static readonly string Mp4WithoutAudio = "./Resources/input_video_only_3sec.mp4";
Expand Down
Binary file not shown.
15 changes: 15 additions & 0 deletions FFMpegCore.Test/VideoTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,21 @@ public void Video_Snapshot_PersistSnapshot()
Assert.AreEqual("png", analysis.PrimaryVideoStream!.CodecName);
}

[TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_Snapshot_Rotated_PersistSnapshot()
{
using var outputPath = new TemporaryFile("out.png");
var input = FFProbe.Analyse(TestResources.Mp4VideoRotationNegative);

FFMpeg.Snapshot(TestResources.Mp4VideoRotationNegative, outputPath);

var analysis = FFProbe.Analyse(outputPath);
// height and width should be swapped
Assert.AreEqual(input.PrimaryVideoStream!.Height, analysis.PrimaryVideoStream!.Width);
Assert.AreEqual(input.PrimaryVideoStream.Width, analysis.PrimaryVideoStream!.Height);
Assert.AreEqual("png", analysis.PrimaryVideoStream!.CodecName);
}

[TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_GifSnapshot_PersistSnapshot()
{
Expand Down
8 changes: 7 additions & 1 deletion FFMpegCore/FFMpeg/SnapshotArgumentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) Bui
}

var currentSize = new Size(source.PrimaryVideoStream.Width, source.PrimaryVideoStream.Height);
if (source.PrimaryVideoStream.Rotation == 90 || source.PrimaryVideoStream.Rotation == 180)
if (IsRotated(source.PrimaryVideoStream.Rotation))
{
currentSize = new Size(source.PrimaryVideoStream.Height, source.PrimaryVideoStream.Width);
}
Expand All @@ -88,4 +88,10 @@ public static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) Bui

return null;
}

private static bool IsRotated(int rotation)
{
var absRotation = Math.Abs(rotation);
return absRotation == 90 || absRotation == 180;
}
}

0 comments on commit 82cc971

Please sign in to comment.