mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] Enable basic video support (mp4 only) (#1274)
* [feature] basic video support * fix missing semicolon * replace text shadow with stacked icons Co-authored-by: f0x <f0x@cthu.lu>
This commit is contained in:
@@ -88,11 +88,11 @@ func (p *ProcessingMedia) LoadAttachment(ctx context.Context) (*gtsmodel.MediaAt
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.loadThumb(ctx); err != nil {
|
||||
if err := p.loadFullSize(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.loadFullSize(ctx); err != nil {
|
||||
if err := p.loadThumb(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -128,7 +128,6 @@ func (p *ProcessingMedia) loadThumb(ctx context.Context) error {
|
||||
switch processState(thumbState) {
|
||||
case received:
|
||||
// we haven't processed a thumbnail for this media yet so do it now
|
||||
|
||||
// check if we need to create a blurhash or if there's already one set
|
||||
var createBlurhash bool
|
||||
if p.attachment.Blurhash == "" {
|
||||
@@ -136,27 +135,46 @@ func (p *ProcessingMedia) loadThumb(ctx context.Context) error {
|
||||
createBlurhash = true
|
||||
}
|
||||
|
||||
// stream the original file out of storage
|
||||
stored, err := p.storage.GetStream(ctx, p.attachment.File.Path)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("loadThumb: error fetching file from storage: %s", err)
|
||||
var (
|
||||
thumb *mediaMeta
|
||||
err error
|
||||
)
|
||||
switch ct := p.attachment.File.ContentType; ct {
|
||||
case mimeImageJpeg, mimeImagePng, mimeImageWebp, mimeImageGif:
|
||||
// thumbnail the image from the original stored full size version
|
||||
stored, err := p.storage.GetStream(ctx, p.attachment.File.Path)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("loadThumb: error fetching file from storage: %s", err)
|
||||
atomic.StoreInt32(&p.thumbState, int32(errored))
|
||||
return p.err
|
||||
}
|
||||
|
||||
thumb, err = deriveThumbnailFromImage(stored, ct, createBlurhash)
|
||||
|
||||
// try to close the stored stream we had open, no matter what
|
||||
if closeErr := stored.Close(); closeErr != nil {
|
||||
log.Errorf("error closing stream: %s", closeErr)
|
||||
}
|
||||
|
||||
// now check if we managed to get a thumbnail
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("loadThumb: error deriving thumbnail: %s", err)
|
||||
atomic.StoreInt32(&p.thumbState, int32(errored))
|
||||
return p.err
|
||||
}
|
||||
case mimeVideoMp4:
|
||||
// create a generic thumbnail based on video height + width
|
||||
thumb, err = deriveThumbnailFromVideo(p.attachment.FileMeta.Original.Height, p.attachment.FileMeta.Original.Width)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("loadThumb: error deriving thumbnail: %s", err)
|
||||
atomic.StoreInt32(&p.thumbState, int32(errored))
|
||||
return p.err
|
||||
}
|
||||
default:
|
||||
p.err = fmt.Errorf("loadThumb: content type %s not a processible image type", ct)
|
||||
atomic.StoreInt32(&p.thumbState, int32(errored))
|
||||
return p.err
|
||||
}
|
||||
defer stored.Close()
|
||||
|
||||
// stream the file from storage straight into the derive thumbnail function
|
||||
thumb, err := deriveThumbnail(stored, p.attachment.File.ContentType, createBlurhash)
|
||||
if err != nil {
|
||||
p.err = fmt.Errorf("loadThumb: error deriving thumbnail: %s", err)
|
||||
atomic.StoreInt32(&p.thumbState, int32(errored))
|
||||
return p.err
|
||||
}
|
||||
|
||||
// Close stored media now we're done
|
||||
if err := stored.Close(); err != nil {
|
||||
log.Errorf("loadThumb: error closing stored full size: %s", err)
|
||||
}
|
||||
|
||||
// put the thumbnail in storage
|
||||
if err := p.storage.Put(ctx, p.attachment.Thumbnail.Path, thumb.small); err != nil && err != storage.ErrAlreadyExists {
|
||||
@@ -195,7 +213,7 @@ func (p *ProcessingMedia) loadFullSize(ctx context.Context) error {
|
||||
switch processState(fullSizeState) {
|
||||
case received:
|
||||
var err error
|
||||
var decoded *imageMeta
|
||||
var decoded *mediaMeta
|
||||
|
||||
// stream the original file out of storage...
|
||||
stored, err := p.storage.GetStream(ctx, p.attachment.File.Path)
|
||||
@@ -218,6 +236,8 @@ func (p *ProcessingMedia) loadFullSize(ctx context.Context) error {
|
||||
decoded, err = decodeImage(stored, ct)
|
||||
case mimeImageGif:
|
||||
decoded, err = decodeGif(stored)
|
||||
case mimeVideoMp4:
|
||||
decoded, err = decodeVideo(stored, ct)
|
||||
default:
|
||||
err = fmt.Errorf("loadFullSize: content type %s not a processible image type", ct)
|
||||
}
|
||||
@@ -295,7 +315,7 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// bail if this is a type we can't process
|
||||
if !supportedImage(contentType) {
|
||||
if !supportedAttachment(contentType) {
|
||||
return fmt.Errorf("store: media type %s not (yet) supported", contentType)
|
||||
}
|
||||
|
||||
@@ -338,6 +358,10 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||
// can't terminate if we don't know the file size, so just store the multiReader
|
||||
readerToStore = multiReader
|
||||
}
|
||||
case mimeMp4:
|
||||
p.attachment.Type = gtsmodel.FileTypeVideo
|
||||
// nothing to terminate, we can just store the multireader
|
||||
readerToStore = multiReader
|
||||
default:
|
||||
return fmt.Errorf("store: couldn't process %s", extension)
|
||||
}
|
||||
|
Reference in New Issue
Block a user