diff --git a/AobaCore/AobaCore.csproj b/AobaCore/AobaCore.csproj index 4d3e6b0..374e214 100644 --- a/AobaCore/AobaCore.csproj +++ b/AobaCore/AobaCore.csproj @@ -7,6 +7,7 @@ + diff --git a/AobaCore/Services/ThumbnailService.cs b/AobaCore/Services/ThumbnailService.cs index 2dcfa21..ae34c43 100644 --- a/AobaCore/Services/ThumbnailService.cs +++ b/AobaCore/Services/ThumbnailService.cs @@ -1,5 +1,8 @@ using AobaCore.Models; +using FFMpegCore; +using FFMpegCore.Pipes; + using MaybeError.Errors; using MongoDB.Bson; @@ -44,16 +47,18 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService) try { - var mediaData = await _gridfs.OpenDownloadStreamAsync(media.MediaId, new GridFSDownloadOptions { Seekable = true }, cancellationToken); + using var mediaData = await _gridfs.OpenDownloadStreamAsync(media.MediaId, new GridFSDownloadOptions { Seekable = true }, cancellationToken); var thumb = await GenerateThumbnailAsync(mediaData, size, media.MediaType, media.Ext, cancellationToken); if (thumb.HasError) return thumb.Error; cancellationToken.ThrowIfCancellationRequested(); +#if !DEBUG var thumbId = await _gridfs.UploadFromStreamAsync($"{media.Filename}.webp", thumb, cancellationToken: CancellationToken.None); var update = Builders.Update.Set(t => t.Sizes[size], thumbId); await _thumbnails.UpdateOneAsync(t => t.Id == id, update, cancellationToken: CancellationToken.None); +#endif thumb.Value.Position = 0; return thumb; } catch (Exception ex) { @@ -101,6 +106,7 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService) var img = Image.Load(stream); img.Mutate(o => { + var size = o.Resize(new ResizeOptions { Position = AnchorPositionMode.Center, @@ -116,7 +122,20 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService) public async Task> GenerateVideoThumbnailAsync(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default) { - return new NotImplementedException(); + var w = (int)size; + var source = new MemoryStream(); + data.CopyTo(source); + source.Position = 0; + var output = new MemoryStream(); + await FFMpegArguments.FromPipeInput(new StreamPipeSource(source)) + .OutputToPipe(new StreamPipeSink(output), opt => + { + opt.WithCustomArgument($"-t 5 -vf \"crop='min(in_w,in_h)':'min(in_w,in_h)',scale={w}:{w}\" -loop 0") + .ForceFormat("webp"); + }).ProcessAsynchronously(); + output.Position = 0; + + return output; } public async Task> GenerateDocumentThumbnailAsync(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default) diff --git a/AobaServer/AobaServer.csproj b/AobaServer/AobaServer.csproj index 937446b..f421437 100644 --- a/AobaServer/AobaServer.csproj +++ b/AobaServer/AobaServer.csproj @@ -16,8 +16,8 @@ all - - + + diff --git a/AobaServer/Dockerfile b/AobaServer/Dockerfile index f407b4d..71f720c 100644 --- a/AobaServer/Dockerfile +++ b/AobaServer/Dockerfile @@ -57,4 +57,5 @@ RUN dotnet publish "./AobaServer.csproj" -c $BUILD_CONFIGURATION -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . +RUN sudo apt-get install -y ffmpeg libgdiplus ENTRYPOINT ["dotnet", "AobaServer.dll"]