A fairly unusual php2Bluesky issue was raised recently, via Github, where when a site was being used as a link card and the main image on that site was a GIF it was being converted and sent to Bluesky as a video, which it didn’t like.
Invalid app.bsky.feed.post record:
Expected "image/*" (got "video/mp4")
at $.record.embed.external.thumb.mimeType
I suppose that this makes sense – there can’t be many sites with a GIF as the associated image and Bluesky wouldn’t be expecting that.
What to do about it?
This presented an interesting challenge – just what should I do about it? The options seemed to be:
- throw an error and let whatever was calling php2Bluesky deal with it
- use the fallback option the user has provided on creating the php2Bluesky instance
- convert the GIF to something else
I chose to go with option three but I then needed to decide:
- what should I convert it to?
- which frame from the GIF should I use?
- what should I do about any transparency?
Stick with what you know
A fairly obvious way forward would have been to have used Imagick and done something like this:
$image = new Imagick($gifFile);
$image->setIteratorIndex(0);
$image->setImageBackgroundColor('white');
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('jpeg');
$image->setImageCompressionQuality(90);
$image->writeImage($outputFile);
$image->clear();
$image->destroy();
The problem with this was that it created a new dependency on php2Bluesky which I wanted to avoid. Given that ffmpeg is already a dependency that is required for converting GIFs to videos I decided to use this instead:
$cmd = sprintf(
'ffmpeg -hide_banner -y -i %s -frames:v 1 %s 2>&1',
escapeshellarg($gifFile),
escapeshellarg($outputFile)
);
exec($cmd, $output, $returnCode);
This takes the first frame from the GIF and outputs it to a JPEG image, converting any transparency to white space.
To this end I have added two new functions: getffmpegPath() and convertGifToImage() which check if and where ffmpeg is installed and converts a passed GIF to an image respectively. The main process now checks to see if a link card has a GIF associated and calls convertGifToImage() to handle it.
Important note: you will need version 9 or above of ffmpeg (and ffprobe) for this to work. You can download the latest version for your machine here.
Another edge case sorted. As ever I am grateful for those users of php2Bluesky who have reported these issues so that I can get them resolved. If you are interested you can download the code from my Github page.