Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b34f7436c2 | |||
| 8b5803c085 | |||
| 5e2a7b53c9 | |||
| d88cfa2cd3 |
@@ -22,17 +22,20 @@ public class Media
|
|||||||
public static readonly Dictionary<string, MediaType> KnownTypes = new()
|
public static readonly Dictionary<string, MediaType> KnownTypes = new()
|
||||||
{
|
{
|
||||||
{ ".jpg", MediaType.Image },
|
{ ".jpg", MediaType.Image },
|
||||||
{ ".avif", MediaType.Image },
|
|
||||||
{ ".jpeg", MediaType.Image },
|
{ ".jpeg", MediaType.Image },
|
||||||
|
{ ".jxr", MediaType.Image },
|
||||||
|
{ ".avif", MediaType.Image },
|
||||||
{ ".png", MediaType.Image },
|
{ ".png", MediaType.Image },
|
||||||
{ ".apng", MediaType.Image },
|
{ ".apng", MediaType.Image },
|
||||||
{ ".webp", MediaType.Image },
|
{ ".webp", MediaType.Image },
|
||||||
|
{ ".qoi", MediaType.Image },
|
||||||
{ ".ico", MediaType.Image },
|
{ ".ico", MediaType.Image },
|
||||||
{ ".gif", MediaType.Image },
|
{ ".gif", MediaType.Image },
|
||||||
{ ".mp3", MediaType.Audio },
|
{ ".mp3", MediaType.Audio },
|
||||||
{ ".flac", MediaType.Audio },
|
{ ".flac", MediaType.Audio },
|
||||||
{ ".alac", MediaType.Audio },
|
{ ".alac", MediaType.Audio },
|
||||||
{ ".mp4", MediaType.Video },
|
{ ".mp4", MediaType.Video },
|
||||||
|
{ ".m4v", MediaType.Video },
|
||||||
{ ".webm", MediaType.Video },
|
{ ".webm", MediaType.Video },
|
||||||
{ ".mov", MediaType.Video },
|
{ ".mov", MediaType.Video },
|
||||||
{ ".avi", MediaType.Video },
|
{ ".avi", MediaType.Video },
|
||||||
@@ -50,6 +53,10 @@ public class Media
|
|||||||
{ ".xml", MediaType.Code },
|
{ ".xml", MediaType.Code },
|
||||||
{ ".json", MediaType.Code },
|
{ ".json", MediaType.Code },
|
||||||
{ ".py", MediaType.Code },
|
{ ".py", MediaType.Code },
|
||||||
|
{ ".rs", MediaType.Code },
|
||||||
|
{ ".zed", MediaType.Code },
|
||||||
|
{ ".ts", MediaType.Code },
|
||||||
|
{ ".astro", MediaType.Code },
|
||||||
};
|
};
|
||||||
|
|
||||||
[BsonConstructor]
|
[BsonConstructor]
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using AobaCore.Models;
|
|||||||
|
|
||||||
using MaybeError.Errors;
|
using MaybeError.Errors;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MongoDB.Bson;
|
using MongoDB.Bson;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using MongoDB.Driver.GridFS;
|
using MongoDB.Driver.GridFS;
|
||||||
@@ -69,6 +71,7 @@ public class AobaService(IMongoDatabase db)
|
|||||||
{
|
{
|
||||||
var fileId = await _gridFs.UploadFromStreamAsync(filename, data, cancellationToken: cancellationToken);
|
var fileId = await _gridFs.UploadFromStreamAsync(filename, data, cancellationToken: cancellationToken);
|
||||||
var media = new Media(fileId, filename, owner);
|
var media = new Media(fileId, filename, owner);
|
||||||
|
|
||||||
await AddMediaAsync(media, cancellationToken);
|
await AddMediaAsync(media, cancellationToken);
|
||||||
return media;
|
return media;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace AobaCore.Services;
|
|||||||
public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
|
public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
|
||||||
{
|
{
|
||||||
private readonly GridFSBucket _gridfs = new GridFSBucket(db);
|
private readonly GridFSBucket _gridfs = new GridFSBucket(db);
|
||||||
private Lock _lock = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -121,26 +120,36 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
|
|||||||
public Maybe<Stream> GenerateVideoThumbnail(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default)
|
public Maybe<Stream> GenerateVideoThumbnail(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var w = (int)size;
|
var w = (int)size;
|
||||||
var source = new MemoryStream();
|
var fn = ObjectId.GenerateNewId().ToString();
|
||||||
|
var filePath = $"/tmp/{fn}.in";
|
||||||
|
using var source = new FileStream(filePath, FileMode.CreateNew);
|
||||||
data.CopyTo(source);
|
data.CopyTo(source);
|
||||||
source.Position = 0;
|
source.Flush();
|
||||||
|
source.Dispose();
|
||||||
|
data.Dispose();
|
||||||
|
try
|
||||||
|
{
|
||||||
var output = new MemoryStream();
|
var output = new MemoryStream();
|
||||||
FFMpegArguments.FromPipeInput(new StreamPipeSource(source), opt =>
|
FFMpegArguments.FromFileInput(filePath, false, opt =>
|
||||||
{
|
{
|
||||||
opt.WithCustomArgument("-t 5");
|
opt.WithCustomArgument("-t 5");
|
||||||
}).OutputToPipe(new StreamPipeSink(output), opt =>
|
}).OutputToPipe(new StreamPipeSink(output), opt =>
|
||||||
{
|
{
|
||||||
opt.WithCustomArgument($"-vf \"crop='min(in_w,in_h)':'min(in_w,in_h)',scale={w}:{w}\" -loop 0 -r 15")
|
opt.WithCustomArgument($"-vf \"crop='min(in_w,in_h)':'min(in_w,in_h)',scale={w}:{w}\" -loop 0 -r 15")
|
||||||
.ForceFormat("webp");
|
.ForceFormat("webp");
|
||||||
}).Configure(cfg =>
|
|
||||||
{
|
|
||||||
#if !DEBUG
|
|
||||||
cfg.BinaryFolder = "/usr/bin";
|
|
||||||
#endif
|
|
||||||
}).ProcessSynchronously();
|
}).ProcessSynchronously();
|
||||||
output.Position = 0;
|
output.Position = 0;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
File.Delete(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Maybe<Stream>> GenerateDocumentThumbnailAsync(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default)
|
public async Task<Maybe<Stream>> GenerateDocumentThumbnailAsync(Stream data, ThumbnailSize size, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class MediaController(AobaService aobaService, ILogger<MediaController> l
|
|||||||
[ResponseCache(Duration = int.MaxValue)]
|
[ResponseCache(Duration = int.MaxValue)]
|
||||||
public async Task<IActionResult> MediaAsync(ObjectId id, [FromServices] MongoClient client, CancellationToken cancellationToken)
|
public async Task<IActionResult> MediaAsync(ObjectId id, [FromServices] MongoClient client, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var file = await aobaService.GetFileStreamAsync(id, cancellationToken: cancellationToken);
|
var file = await aobaService.GetFileStreamAsync(id, seekable: true, cancellationToken: cancellationToken);
|
||||||
if (file.HasError)
|
if (file.HasError)
|
||||||
{
|
{
|
||||||
logger.LogError(file.Error.Exception, "Failed to load media stream");
|
logger.LogError(file.Error.Exception, "Failed to load media stream");
|
||||||
|
|||||||
Reference in New Issue
Block a user