Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Video upload recorded with an iPhone results in 422 Unprocessable entity #1688

Closed
kensanata opened this issue Apr 10, 2023 · 11 comments
Closed
Labels
bug Something isn't working

Comments

@kensanata
Copy link
Contributor

Describe the bug with a clear and concise description of what the bug is.

I'm on an iPhone 11 and use Toot! to upload a video somebody sent me from a newer iPhone. On the phone the info I see is:

  • Apple iPhone 14 HEVC
  • 1080p 1080×1920 25MB Dolby Vision
  • 30 FPS
  • 00:23

On the client, I'm getting a message that the upload failed.

On the server, config.yaml says media-video-max-size: 41943040 so size should not be a problem.

The log file says:

timestamp="10/04/2023 17:09:02.737" func=middleware.Logger.func1.1 level=INFO latency=2.359508383s clientIP=… userAgent="Toot!/172 CFNetwork/1404.0.5 Darwin/22.3.0" method=POST statusCode=422 path=/api/v1/media requestID=b6abctw704000xr29nsg msg="Unprocessable Entity: wrote 650B"

Next, I shared the video to a mail that I sent to myself (which reduces the file size by a factor of 10), saved it again, and tried to upload that, from my iPhone 11, same problem.

Next, I downloaded that file to my laptop running a Debian-derived operating system and used Pinafore to upload the video, same problem.

So this problem is unrelated to the client, or the operating system, but it's something about the video file itself. Encoding? I don't know.

IMG_3618.MOV

I attached the second, smaller file.

What's your GoToSocial Version?

v0.7.1

GoToSocial Arch

arm64 Binary

What happened?

I get an error when uploading a short video.

What you expected to happen?

The video to upload successfully.

How to reproduce it?

No idea. But you can take a look at the video here: https://alexschroeder.ch/pics/IMG_3618.MOV

Anything else we need to know?

Nope.

@kensanata kensanata added the bug Something isn't working label Apr 10, 2023
@kensanata
Copy link
Contributor Author

Doing some re-encoding myself results in an MP4 file that I can upload (using Pinafore, same setup that fails with the MOV file).

ffmpeg -i IMG_3618.MOV -q:v 0 IMG_3618.MP4

@NyaaaWhatsUpDoc
Copy link
Member

The issue is that for now we only support mp4 :)

@kensanata
Copy link
Contributor Author

kensanata commented Apr 11, 2023 via email

@daenney
Copy link
Member

daenney commented May 16, 2023

I'm looking at the code, and I think I've figured out why this happens. All the links are to v0.7.1 versions of the code, but it's largely the same in main.

All the way down the call chain, an error will get raised by store:

switch info.Extension {
case "mp4":
p.media.Type = gtsmodel.FileTypeVideo
case "gif":
p.media.Type = gtsmodel.FileTypeImage
case "jpg", "jpeg", "png", "webp":
p.media.Type = gtsmodel.FileTypeImage
if sz > 0 {
// A file size was provided so we can clean exif data from image.
r, err = terminator.Terminate(r, int(sz), info.Extension)
if err != nil {
return fmt.Errorf("error cleaning exif data: %w", err)
}
}
default:
return fmt.Errorf("unsupported file type: %s", info.Extension)
}

That gets bubbled back up (as far as I can see) to

func (p *ProcessingMedia) load(ctx context.Context) (*gtsmodel.MediaAttachment, bool, error) {
and then
func (p *ProcessingMedia) LoadAttachment(ctx context.Context) (*gtsmodel.MediaAttachment, error) {
until we finally get to
attachment, err := media.LoadAttachment(ctx)
if err != nil {
return nil, gtserror.NewErrorUnprocessableEntity(err)
}

That NewUnprocessableEntity retains the original error, and then we get back to

apiAttachment, errWithCode := m.processor.MediaCreate(c.Request.Context(), authed, form)
if errWithCode != nil {
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
return
}

Almost there now, back up

} else {
genericErrorHandler(c, instanceGet, accept, errWithCode)
}

That lands us in

func genericErrorHandler(c *gin.Context, instanceGet func(ctx context.Context) (*apimodel.InstanceV1, gtserror.WithCode), accept string, errWithCode gtserror.WithCode) {
switch accept {
case string(TextHTML):
ctx := c.Request.Context()
instance, err := instanceGet(ctx)
if err != nil {
panic(err)
}
c.HTML(errWithCode.Code(), "error.tmpl", gin.H{
"instance": instance,
"code": errWithCode.Code(),
"error": errWithCode.Safe(),
"requestID": middleware.RequestID(ctx),
})
default:
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
}
}

Since we don't pass a helpText to NewErrorUnprocessableEntity, you end up with just the generic message for the 422 status code.

func NewErrorUnprocessableEntity(original error, helpText ...string) WithCode {
safe := http.StatusText(http.StatusUnprocessableEntity)
if helpText != nil {
safe = safe + ": " + strings.Join(helpText, ": ")
}
return withCode{
original: original,
safe: errors.New(safe),
code: http.StatusUnprocessableEntity,
}
}

If we returned a more specific error from store, we could detect the unsupported file type in the media processor's Create and include a help text that reflects that issue when we create the NewErrorUnprocessableEntity. That would then result in a more helpful message in the API response which should also be displayed in the clients.

@erasmas
Copy link

erasmas commented Jun 13, 2023

Surprisingly, I'm not able to upload an MP4 video either. The video is recorded on iPhone and converted to MP4 specifically for gotosocial but I'm getting HTTP 422. 😕

@Ben02
Copy link

Ben02 commented Jul 12, 2023

I'm not able to upload an MP4 video which is a screen record by iOS. I got HTTP 422 too.

@meljoann
Copy link

Could be related to H.265 vs H.264? I was trying to get my file size down, so tried both. Used Handbrake to compress & encode.

  • H.265 wouldn't upload, with "unprocessable" error message on Elk. ioS 11+ support H.265, so maybe...
  • H.264 worked.

@tsmethurst
Copy link
Contributor

The newest release of the Go mp4 library we use adds a few more mp4 box types to its decodable formats, so that should help a bit: https://github.com/abema/go-mp4/releases/tag/v0.12.0

@tsmethurst
Copy link
Contributor

For future reference, there's a list here of box types that are and aren't currently supported: abema/go-mp4#13

@erasmas
Copy link

erasmas commented Aug 16, 2023

Verified that this issue is still present in 0.11.0. Is there any information that I can provide to help with the fix?

@tsmethurst
Copy link
Contributor

tsmethurst commented Jul 15, 2024

This should be closed by #3090 (tested with the video in the OP)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants