| Name | Message | Date |
|---|---|---|
| 📄 ClipExtractor.cs | 9 days ago | |
| 📄 Ffmpeg.csproj | 9 days ago | |
| 📄 packages.lock.json | 9 days ago | |
| 📄 ServiceCollectionExtensions.cs | 9 days ago | |
| 📄 SubtitleReader.cs | 9 days ago |
📄
src/Infrastructure/Ffmpeg/ClipExtractor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System; using System.Threading.Tasks; using FFMpegCore; using FFMpegCore.Arguments; using FFMpegCore.Enums; using Microsoft.Extensions.Logging; using Slopper.Domain; namespace Slopper.Infrastructure.Ffmpeg; public sealed class ClipExtractor(ILogger<ClipExtractor> logger) { public async Task Clip(MediaItem media, TimeSpan start, TimeSpan duration, string outputPath) { var args = FFMpegArguments .FromFileInput(media.Path) .OutputToFile( outputPath, addArguments: options => options .Seek(start) .EndSeek(start + duration) .WithVideoFilters(filter => filter.HardBurnSubtitle(CreateSubtitleOptions(media))) .WithFastStart() .WithVideoCodec(VideoCodec.LibX264) .WithAudioCodec(AudioCodec.Aac) .WithFramerate(30.0d) .WithVideoBitrate(4000) .WithAudioBitrate(128) .ForceFormat("mp4") ); logger.LogInformation("Running ffmpeg {FfmpegArguments}", args.Arguments); await args.ProcessAsynchronously(); } private static SubtitleHardBurnOptions CreateSubtitleOptions(MediaItem media) => ( media.Subtitles switch { Subtitles.External(var path) => SubtitleHardBurnOptions.Create(path), Subtitles.Embedded(var index) => SubtitleHardBurnOptions.Create(media.Path).SetSubtitleIndex(index), _ => throw new ArgumentException("Unknown subtitle type"), } ).WithParameter( "force_style", "FontName=Segoe UI,FontSize=20,PrimaryColour=&HFFFFFF&,BackColour=&H000000&,BorderStyle=1,Alignment=2" ); }