mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2025-12-14 01:55:45 +00:00
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
97 lines
3.6 KiB
C#
97 lines
3.6 KiB
C#
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
|
|
|
|
using System.Drawing;
|
|
using FFMpegCore.Enums;
|
|
|
|
namespace FFMpegCore;
|
|
|
|
public static class SnapshotArgumentBuilder
|
|
{
|
|
public static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) BuildSnapshotArguments(
|
|
string input,
|
|
IMediaAnalysis source,
|
|
Size? size = null,
|
|
TimeSpan? captureTime = null,
|
|
int? streamIndex = null,
|
|
int inputFileIndex = 0)
|
|
{
|
|
captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
|
|
size = PrepareSnapshotSize(source, size);
|
|
streamIndex ??= source.PrimaryVideoStream?.Index
|
|
?? source.VideoStreams.FirstOrDefault()?.Index
|
|
?? 0;
|
|
|
|
return (FFMpegArguments
|
|
.FromFileInput(input, false, options => options
|
|
.Seek(captureTime)),
|
|
options => options
|
|
.SelectStream((int)streamIndex, inputFileIndex)
|
|
.WithVideoCodec(VideoCodec.Png)
|
|
.WithFrameOutputCount(1)
|
|
.Resize(size));
|
|
}
|
|
|
|
public static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) BuildGifSnapshotArguments(
|
|
string input,
|
|
IMediaAnalysis source,
|
|
Size? size = null,
|
|
TimeSpan? captureTime = null,
|
|
TimeSpan? duration = null,
|
|
int? streamIndex = null,
|
|
int fps = 12)
|
|
{
|
|
var defaultGifOutputSize = new Size(480, -1);
|
|
|
|
captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
|
|
size = PrepareSnapshotSize(source, size) ?? defaultGifOutputSize;
|
|
streamIndex ??= source.PrimaryVideoStream?.Index
|
|
?? source.VideoStreams.FirstOrDefault()?.Index
|
|
?? 0;
|
|
|
|
return (FFMpegArguments
|
|
.FromFileInput(input, false, options => options
|
|
.Seek(captureTime)
|
|
.WithDuration(duration)),
|
|
options => options
|
|
.WithGifPaletteArgument((int)streamIndex, size, fps));
|
|
}
|
|
|
|
private static Size? PrepareSnapshotSize(IMediaAnalysis source, Size? wantedSize)
|
|
{
|
|
if (wantedSize == null || (wantedSize.Value.Height <= 0 && wantedSize.Value.Width <= 0) || source.PrimaryVideoStream == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var currentSize = new Size(source.PrimaryVideoStream.Width, source.PrimaryVideoStream.Height);
|
|
if (IsRotated(source.PrimaryVideoStream.Rotation))
|
|
{
|
|
currentSize = new Size(source.PrimaryVideoStream.Height, source.PrimaryVideoStream.Width);
|
|
}
|
|
|
|
if (wantedSize.Value.Width != currentSize.Width || wantedSize.Value.Height != currentSize.Height)
|
|
{
|
|
if (wantedSize.Value.Width <= 0 && wantedSize.Value.Height > 0)
|
|
{
|
|
var ratio = (double)wantedSize.Value.Height / currentSize.Height;
|
|
return new Size((int)(currentSize.Width * ratio), (int)(currentSize.Height * ratio));
|
|
}
|
|
|
|
if (wantedSize.Value.Height <= 0 && wantedSize.Value.Width > 0)
|
|
{
|
|
var ratio = (double)wantedSize.Value.Width / currentSize.Width;
|
|
return new Size((int)(currentSize.Width * ratio), (int)(currentSize.Height * ratio));
|
|
}
|
|
|
|
return wantedSize;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static bool IsRotated(int rotation)
|
|
{
|
|
var absRotation = Math.Abs(rotation);
|
|
return absRotation == 90 || absRotation == 180;
|
|
}
|
|
}
|