feat(media): repurpose GIFs as video and serve converted mp4 when available
- Classify .gif as EAssetType.Video via MimeTypes (moved image/gif to the Video registry)
- Add MediaRepository.GetConvertedData, served by the existing media/{id} endpoint
when a converted file exists on disk (with a fallback + warning log if missing)
- Expose the converted MIME type on AssetPreviewDto/AlbumAssetPreviewDto
so the frontend can detect video assets from a single MimeType field
This commit is contained in:
@@ -177,6 +177,7 @@ public class AlbumRepository(LactoseDbContext context) : IAlbumRepository {
|
||||
ResolutionHeight = a.ResolutionHeight,
|
||||
HasThumbnail = a.ThumbnailPath != null && a.ThumbnailPath != "",
|
||||
HasPreview = a.PreviewPath != null && a.PreviewPath != "",
|
||||
MimeType = a.ConvertedMimeType != null && a.ConvertedMimeType != "" ? a.ConvertedMimeType : a.MimeType,
|
||||
FileName = accessLevel >= EAccessLevel.Curator ? a.OriginalFilename : null,
|
||||
Visibility = accessLevel >= EAccessLevel.Maintainer ? a.Visibility : null,
|
||||
DeletedAt = accessLevel >= EAccessLevel.Admin || a.UploadedBy == userId ? a.DeletedAt : null
|
||||
|
||||
@@ -317,7 +317,7 @@ public class AssetRepository(LactoseDbContext context, ILogger<AssetRepository>
|
||||
.Where(a => pageIds.Contains(a.Id))
|
||||
.Select(a => new AssetPreviewDto {
|
||||
Id = a.Id,
|
||||
MimeType = a.MimeType,
|
||||
MimeType = a.ConvertedMimeType != null && a.ConvertedMimeType != "" ? a.ConvertedMimeType : a.MimeType,
|
||||
ResolutionWidth = a.ResolutionWidth,
|
||||
ResolutionHeight = a.ResolutionHeight,
|
||||
HasThumbnail = a.ThumbnailPath != null && a.ThumbnailPath != "",
|
||||
@@ -459,7 +459,6 @@ public class AssetRepository(LactoseDbContext context, ILogger<AssetRepository>
|
||||
return new Butter.Dtos.Asset.AssetBrowseResultDto {
|
||||
Directories = dirs,
|
||||
Assets = assetDtos,
|
||||
CurrentPath = currentPath,
|
||||
TotalAssetCount = totalAtLevel
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,4 +33,13 @@ public interface IMediaRepository : IDisposable {
|
||||
/// <param name="accessLevel">The requesting user's access level.</param>
|
||||
/// <returns>A <see cref="MediaDto"/> containing the media data, or null if not found or unauthorized.</returns>
|
||||
public MediaDto? GetPreviewData(Guid id, Guid? userId, EAccessLevel accessLevel = EAccessLevel.User);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the converted media data (e.g. the mp4 for an animated GIF).
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the media.</param>
|
||||
/// <param name="userId">The ID of the user requesting the media.</param>
|
||||
/// <param name="accessLevel">The requesting user's access level.</param>
|
||||
/// <returns>A <see cref="MediaDto"/> containing the converted media data, or null if the asset has no converted file or is not visible.</returns>
|
||||
public MediaDto? GetConvertedData(Guid id, Guid? userId, EAccessLevel accessLevel = EAccessLevel.User);
|
||||
}
|
||||
@@ -93,6 +93,20 @@ public class MediaRepository(LactoseDbContext context, IPersonRepository personR
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MediaDto? GetConvertedData(Guid id, Guid? userId, EAccessLevel accessLevel = EAccessLevel.User) {
|
||||
var media = GetVisibleAsset(id, userId, accessLevel);
|
||||
|
||||
if (media == null) return null;
|
||||
|
||||
if (string.IsNullOrEmpty(media.ConvertedPath) || string.IsNullOrEmpty(media.ConvertedMimeType)) return null;
|
||||
|
||||
return new MediaDto {
|
||||
MimeType = media.ConvertedMimeType,
|
||||
Path = media.ConvertedPath
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() {
|
||||
context.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user