mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2026-01-07 06:53:16 -06:00
[bugfix] Parse video metadata more accurately; allow Range in fileserver (#1342)
* don't serve unused fields for video attachments * parse video bitrate + duration more accurately * use ServeContent where appropriate to respect Range * abstract temp file seeker into its own function
This commit is contained in:
parent
fe3e9ede52
commit
d4cddf460a
14 changed files with 216 additions and 92 deletions
|
|
@ -201,7 +201,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessful() {
|
|||
Size: "512x288",
|
||||
Aspect: 1.7777778,
|
||||
},
|
||||
Focus: apimodel.MediaFocus{
|
||||
Focus: &apimodel.MediaFocus{
|
||||
X: -0.5,
|
||||
Y: 0.5,
|
||||
},
|
||||
|
|
@ -290,7 +290,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessfulV2() {
|
|||
Size: "512x288",
|
||||
Aspect: 1.7777778,
|
||||
},
|
||||
Focus: apimodel.MediaFocus{
|
||||
Focus: &apimodel.MediaFocus{
|
||||
X: -0.5,
|
||||
Y: 0.5,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ func (suite *MediaUpdateTestSuite) TestUpdateImage() {
|
|||
suite.EqualValues(apimodel.MediaMeta{
|
||||
Original: apimodel.MediaDimensions{Width: 800, Height: 450, FrameRate: "", Duration: 0, Bitrate: 0, Size: "800x450", Aspect: 1.7777778},
|
||||
Small: apimodel.MediaDimensions{Width: 256, Height: 144, FrameRate: "", Duration: 0, Bitrate: 0, Size: "256x144", Aspect: 1.7777778},
|
||||
Focus: apimodel.MediaFocus{X: -0.1, Y: 0.3},
|
||||
Focus: &apimodel.MediaFocus{X: -0.1, Y: 0.3},
|
||||
}, attachmentReply.Meta)
|
||||
suite.Equal(toUpdate.Blurhash, attachmentReply.Blurhash)
|
||||
suite.Equal(toUpdate.ID, attachmentReply.ID)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/iotools"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
)
|
||||
|
|
@ -128,8 +129,34 @@ func (m *Module) ServeFile(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// we're good, return the slurped bytes + the rest of the content
|
||||
c.DataFromReader(http.StatusOK, content.ContentLength, format, io.MultiReader(
|
||||
bytes.NewReader(b), content.Content,
|
||||
), nil)
|
||||
// reconstruct the original content reader
|
||||
r := io.MultiReader(bytes.NewReader(b), content.Content)
|
||||
|
||||
// Check the Range header: if this is a simple query for the whole file, we can return it now.
|
||||
if c.GetHeader("Range") == "" && c.GetHeader("If-Range") == "" {
|
||||
c.DataFromReader(http.StatusOK, content.ContentLength, format, r, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Range is set, so we need a ReadSeeker to pass to the ServeContent function.
|
||||
tfs, err := iotools.TempFileSeeker(r)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("ServeFile: error creating temp file seeker: %w", err)
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := tfs.Close(); err != nil {
|
||||
log.Errorf("ServeFile: error closing temp file seeker: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// to avoid ServeContent wasting time seeking for the
|
||||
// mime type, set this header already since we know it
|
||||
c.Header("Content-Type", format)
|
||||
|
||||
// allow ServeContent to handle the rest of the request;
|
||||
// it will handle Range as appropriate, and write correct
|
||||
// response headers, http code, etc
|
||||
http.ServeContent(c.Writer, c.Request, fileName, content.ContentUpdated, tfs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,40 +98,12 @@ type Attachment struct {
|
|||
//
|
||||
// swagger:model mediaMeta
|
||||
type MediaMeta struct {
|
||||
Length string `json:"length,omitempty"`
|
||||
// Duration of the media in seconds.
|
||||
// Only set for video and audio.
|
||||
// example: 5.43
|
||||
Duration float32 `json:"duration,omitempty"`
|
||||
// Framerate of the media.
|
||||
// Only set for video and gifs.
|
||||
// example: 30
|
||||
FPS uint16 `json:"fps,omitempty"`
|
||||
// Size of the media, in the format `[width]x[height]`.
|
||||
// Not set for audio.
|
||||
// example: 1920x1080
|
||||
Size string `json:"size,omitempty"`
|
||||
// Width of the media in pixels.
|
||||
// Not set for audio.
|
||||
// example: 1920
|
||||
Width int `json:"width,omitempty"`
|
||||
// Height of the media in pixels.
|
||||
// Not set for audio.
|
||||
// example: 1080
|
||||
Height int `json:"height,omitempty"`
|
||||
// Aspect ratio of the media.
|
||||
// Equal to width / height.
|
||||
// example: 1.777777778
|
||||
Aspect float32 `json:"aspect,omitempty"`
|
||||
AudioEncode string `json:"audio_encode,omitempty"`
|
||||
AudioBitrate string `json:"audio_bitrate,omitempty"`
|
||||
AudioChannels string `json:"audio_channels,omitempty"`
|
||||
// Dimensions of the original media.
|
||||
Original MediaDimensions `json:"original"`
|
||||
// Dimensions of the thumbnail/small version of the media.
|
||||
Small MediaDimensions `json:"small,omitempty"`
|
||||
// Focus data for the media.
|
||||
Focus MediaFocus `json:"focus,omitempty"`
|
||||
Focus *MediaFocus `json:"focus,omitempty"`
|
||||
}
|
||||
|
||||
// MediaFocus models the focal point of a piece of media.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package model
|
|||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Content wraps everything needed to serve a blob of content (some kind of media) through the API.
|
||||
|
|
@ -29,6 +30,8 @@ type Content struct {
|
|||
ContentType string
|
||||
// ContentLength in bytes
|
||||
ContentLength int64
|
||||
// Time when the content was last updated.
|
||||
ContentUpdated time.Time
|
||||
// Actual content
|
||||
Content io.ReadCloser
|
||||
// Resource URL to forward to if the file can be fetched from the storage directly (e.g signed S3 URL)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue