mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2024-11-14 10:14:12 +01:00
Merge branch 'master' of https://github.com/rosenbjerg/FFMpegCore
This commit is contained in:
commit
78919dcdcf
8 changed files with 39 additions and 21 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
@ -1,8 +1,5 @@
|
||||||
name: CI
|
name: CI
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -159,7 +159,7 @@ private void ConvertToStreamPipe(params IArgument[] inputArguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Convert(ContainerFormat type, Action<MediaAnalysis> validationMethod, params IArgument[] inputArguments)
|
public void Convert(ContainerFormat type, Action<IMediaAnalysis> validationMethod, params IArgument[] inputArguments)
|
||||||
{
|
{
|
||||||
var output = Input.OutputLocation(type);
|
var output = Input.OutputLocation(type);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ public static class FFMpeg
|
||||||
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
||||||
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
||||||
/// <returns>Bitmap with the requested snapshot.</returns>
|
/// <returns>Bitmap with the requested snapshot.</returns>
|
||||||
public static bool Snapshot(MediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null)
|
public static bool Snapshot(IMediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null)
|
||||||
{
|
{
|
||||||
if (Path.GetExtension(output) != FileExtension.Png)
|
if (Path.GetExtension(output) != FileExtension.Png)
|
||||||
output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png;
|
output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png;
|
||||||
|
@ -40,7 +40,7 @@ public static bool Snapshot(MediaAnalysis source, string output, Size? size = nu
|
||||||
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
||||||
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
||||||
/// <returns>Bitmap with the requested snapshot.</returns>
|
/// <returns>Bitmap with the requested snapshot.</returns>
|
||||||
public static Task<bool> SnapshotAsync(MediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null)
|
public static Task<bool> SnapshotAsync(IMediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null)
|
||||||
{
|
{
|
||||||
if (Path.GetExtension(output) != FileExtension.Png)
|
if (Path.GetExtension(output) != FileExtension.Png)
|
||||||
output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png;
|
output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png;
|
||||||
|
@ -58,7 +58,7 @@ public static Task<bool> SnapshotAsync(MediaAnalysis source, string output, Size
|
||||||
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
||||||
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
||||||
/// <returns>Bitmap with the requested snapshot.</returns>
|
/// <returns>Bitmap with the requested snapshot.</returns>
|
||||||
public static Bitmap Snapshot(MediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
public static Bitmap Snapshot(IMediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
||||||
{
|
{
|
||||||
var arguments = BuildSnapshotArguments(source, size, captureTime);
|
var arguments = BuildSnapshotArguments(source, size, captureTime);
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
|
@ -78,7 +78,7 @@ public static Bitmap Snapshot(MediaAnalysis source, Size? size = null, TimeSpan?
|
||||||
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
/// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
|
||||||
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
/// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
|
||||||
/// <returns>Bitmap with the requested snapshot.</returns>
|
/// <returns>Bitmap with the requested snapshot.</returns>
|
||||||
public static async Task<Bitmap> SnapshotAsync(MediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
public static async Task<Bitmap> SnapshotAsync(IMediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
||||||
{
|
{
|
||||||
var arguments = BuildSnapshotArguments(source, size, captureTime);
|
var arguments = BuildSnapshotArguments(source, size, captureTime);
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
|
@ -92,7 +92,7 @@ await arguments
|
||||||
return new Bitmap(ms);
|
return new Bitmap(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FFMpegArguments BuildSnapshotArguments(MediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
private static FFMpegArguments BuildSnapshotArguments(IMediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
|
||||||
{
|
{
|
||||||
captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
|
captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
|
||||||
size = PrepareSnapshotSize(source, size);
|
size = PrepareSnapshotSize(source, size);
|
||||||
|
@ -104,7 +104,7 @@ private static FFMpegArguments BuildSnapshotArguments(MediaAnalysis source, Size
|
||||||
.Resize(size);
|
.Resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Size? PrepareSnapshotSize(MediaAnalysis source, Size? wantedSize)
|
private static Size? PrepareSnapshotSize(IMediaAnalysis source, Size? wantedSize)
|
||||||
{
|
{
|
||||||
if (wantedSize == null || (wantedSize.Value.Height <= 0 && wantedSize.Value.Width <= 0))
|
if (wantedSize == null || (wantedSize.Value.Height <= 0 && wantedSize.Value.Width <= 0))
|
||||||
return null;
|
return null;
|
||||||
|
@ -143,7 +143,7 @@ private static FFMpegArguments BuildSnapshotArguments(MediaAnalysis source, Size
|
||||||
/// <param name="multithreaded">Is encoding multithreaded.</param>
|
/// <param name="multithreaded">Is encoding multithreaded.</param>
|
||||||
/// <returns>Output video information.</returns>
|
/// <returns>Output video information.</returns>
|
||||||
public static bool Convert(
|
public static bool Convert(
|
||||||
MediaAnalysis source,
|
IMediaAnalysis source,
|
||||||
string output,
|
string output,
|
||||||
ContainerFormat format,
|
ContainerFormat format,
|
||||||
Speed speed = Speed.SuperFast,
|
Speed speed = Speed.SuperFast,
|
||||||
|
@ -235,7 +235,7 @@ public static bool PosterWithAudio(string image, string audio, string output)
|
||||||
/// <param name="output">Output video file.</param>
|
/// <param name="output">Output video file.</param>
|
||||||
/// <param name="videos">List of vides that need to be joined together.</param>
|
/// <param name="videos">List of vides that need to be joined together.</param>
|
||||||
/// <returns>Output video information.</returns>
|
/// <returns>Output video information.</returns>
|
||||||
public static bool Join(string output, params MediaAnalysis[] videos)
|
public static bool Join(string output, params IMediaAnalysis[] videos)
|
||||||
{
|
{
|
||||||
var temporaryVideoParts = videos.Select(video =>
|
var temporaryVideoParts = videos.Select(video =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace FFMpegCore.Pipes
|
namespace FFMpegCore.Pipes
|
||||||
{
|
{
|
||||||
static class PipeHelpers
|
static class PipeHelpers
|
||||||
{
|
{
|
||||||
|
static readonly string PipePrefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_");
|
||||||
|
|
||||||
public static string GetUnqiuePipeName() => "FFMpegCore_" + Guid.NewGuid();
|
public static string GetUnqiuePipeName() => "FFMpegCore_" + Guid.NewGuid();
|
||||||
|
|
||||||
public static string GetPipePath(string pipeName)
|
public static string GetPipePath(string pipeName)
|
||||||
|
@ -12,7 +15,7 @@ public static string GetPipePath(string pipeName)
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return $@"\\.\pipe\{pipeName}";
|
return $@"\\.\pipe\{pipeName}";
|
||||||
else
|
else
|
||||||
return $"unix:/tmp/CoreFxPipe_{pipeName}"; // dotnet uses unix sockets on unix, for more see https://github.com/dotnet/runtime/issues/24390
|
return $"unix:{PipePrefix}{pipeName}"; // dotnet uses unix sockets on unix, for more see https://github.com/dotnet/runtime/issues/24390
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ namespace FFMpegCore
|
||||||
{
|
{
|
||||||
public static class FFProbe
|
public static class FFProbe
|
||||||
{
|
{
|
||||||
public static MediaAnalysis Analyse(string filePath, int outputCapacity = int.MaxValue)
|
public static IMediaAnalysis Analyse(string filePath, int outputCapacity = int.MaxValue)
|
||||||
{
|
{
|
||||||
using var instance = PrepareInstance(filePath, outputCapacity);
|
using var instance = PrepareInstance(filePath, outputCapacity);
|
||||||
instance.BlockUntilFinished();
|
instance.BlockUntilFinished();
|
||||||
return ParseOutput(filePath, instance);
|
return ParseOutput(filePath, instance);
|
||||||
}
|
}
|
||||||
public static MediaAnalysis Analyse(System.IO.Stream stream, int outputCapacity = int.MaxValue)
|
public static IMediaAnalysis Analyse(System.IO.Stream stream, int outputCapacity = int.MaxValue)
|
||||||
{
|
{
|
||||||
var streamPipeSource = new StreamPipeSource(stream);
|
var streamPipeSource = new StreamPipeSource(stream);
|
||||||
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
||||||
|
@ -40,13 +40,13 @@ public static MediaAnalysis Analyse(System.IO.Stream stream, int outputCapacity
|
||||||
|
|
||||||
return ParseOutput(pipeArgument.PipePath, instance);
|
return ParseOutput(pipeArgument.PipePath, instance);
|
||||||
}
|
}
|
||||||
public static async Task<MediaAnalysis> AnalyseAsync(string filePath, int outputCapacity = int.MaxValue)
|
public static async Task<IMediaAnalysis> AnalyseAsync(string filePath, int outputCapacity = int.MaxValue)
|
||||||
{
|
{
|
||||||
using var instance = PrepareInstance(filePath, outputCapacity);
|
using var instance = PrepareInstance(filePath, outputCapacity);
|
||||||
await instance.FinishedRunning();
|
await instance.FinishedRunning();
|
||||||
return ParseOutput(filePath, instance);
|
return ParseOutput(filePath, instance);
|
||||||
}
|
}
|
||||||
public static async Task<MediaAnalysis> AnalyseAsync(System.IO.Stream stream, int outputCapacity = int.MaxValue)
|
public static async Task<IMediaAnalysis> AnalyseAsync(System.IO.Stream stream, int outputCapacity = int.MaxValue)
|
||||||
{
|
{
|
||||||
var streamPipeSource = new StreamPipeSource(stream);
|
var streamPipeSource = new StreamPipeSource(stream);
|
||||||
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
||||||
|
@ -73,7 +73,7 @@ public static async Task<MediaAnalysis> AnalyseAsync(System.IO.Stream stream, in
|
||||||
return ParseOutput(pipeArgument.PipePath, instance);
|
return ParseOutput(pipeArgument.PipePath, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaAnalysis ParseOutput(string filePath, Instance instance)
|
private static IMediaAnalysis ParseOutput(string filePath, Instance instance)
|
||||||
{
|
{
|
||||||
var json = string.Join(string.Empty, instance.OutputData);
|
var json = string.Join(string.Empty, instance.OutputData);
|
||||||
var ffprobeAnalysis = JsonSerializer.Deserialize<FFProbeAnalysis>(json, new JsonSerializerOptions
|
var ffprobeAnalysis = JsonSerializer.Deserialize<FFProbeAnalysis>(json, new JsonSerializerOptions
|
||||||
|
|
18
FFMpegCore/FFProbe/IMediaAnalysis.cs
Normal file
18
FFMpegCore/FFProbe/IMediaAnalysis.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FFMpegCore
|
||||||
|
{
|
||||||
|
public interface IMediaAnalysis
|
||||||
|
{
|
||||||
|
string Path { get; }
|
||||||
|
string Extension { get; }
|
||||||
|
TimeSpan Duration { get; }
|
||||||
|
MediaFormat Format { get; }
|
||||||
|
AudioStream PrimaryAudioStream { get; }
|
||||||
|
VideoStream PrimaryVideoStream { get; }
|
||||||
|
List<VideoStream> VideoStreams { get; }
|
||||||
|
List<AudioStream> AudioStreams { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
namespace FFMpegCore
|
namespace FFMpegCore
|
||||||
{
|
{
|
||||||
public class MediaAnalysis
|
internal class MediaAnalysis : IMediaAnalysis
|
||||||
{
|
{
|
||||||
private static readonly Regex DurationRegex = new Regex("^(\\d{1,2}:\\d{1,2}:\\d{1,2}(.\\d{1,7})?)", RegexOptions.Compiled);
|
private static readonly Regex DurationRegex = new Regex("^(\\d{1,2}:\\d{1,2}:\\d{1,2}(.\\d{1,7})?)", RegexOptions.Compiled);
|
||||||
internal MediaAnalysis(string path, FFProbeAnalysis analysis)
|
internal MediaAnalysis(string path, FFProbeAnalysis analysis)
|
||||||
|
|
|
@ -12,7 +12,7 @@ public static void ConversionSizeExceptionCheck(Image image)
|
||||||
ConversionSizeExceptionCheck(image.Size);
|
ConversionSizeExceptionCheck(image.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConversionSizeExceptionCheck(MediaAnalysis info)
|
public static void ConversionSizeExceptionCheck(IMediaAnalysis info)
|
||||||
{
|
{
|
||||||
ConversionSizeExceptionCheck(new Size(info.PrimaryVideoStream.Width, info.PrimaryVideoStream.Height));
|
ConversionSizeExceptionCheck(new Size(info.PrimaryVideoStream.Width, info.PrimaryVideoStream.Height));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue