Skip to content

Uploading animated GIFs

You can use any of our public icons when creating your content, but you can also upload your own animated GIFs.

In this example, we’ll be uploading this animated GIF An animated GIF icon.

The animated GIF upload process works exactly the same as uploading custom icons

Here are the requirements for animated GIFs

  • Must be exactly 16×16 pixels in dimensions
  • Must be in GIF or PNG format

Unlike regular icons, animated GIFs cannot use autoConvert=true because the conversion process would remove the animation and convert it to a static PNG.

If your GIF doesn’t meet these requirements, you’ll receive a validation error.

import { readFileSync } from 'node:fs';
const gifBuffer = readFileSync('./animated-icon.gif');
const gifFile = new Blob([gifBuffer], { type: 'image/gif' });
const url = `https://api.yotoplay.com/media/displayIcons/user/me/upload?autoConvert=false&filename=animated-icon`;
const uploadResponse = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'image/gif',
},
body: gifFile,
});
const uploadResult = await uploadResponse.json();

When uploading animated GIFs, you must use these specific parameters:

  • autoConvert (boolean): Must be set to false for animated GIFs. When false, the server will validate that your GIF is exactly 16×16 pixels and preserve the animation.

  • filename (string): Optional custom filename for your animated icon. The .gif extension will be automatically determined from the uploaded file’s MIME type.

If your GIF doesn’t meet these requirements, you’ll receive a validation error.

Once uploaded successfully, you’ll receive a response containing:

{
"displayIcon": {
"mediaId": "XBkuY6DBFn5iRfFS6nV6CTWaCrEvBOOX8nzV9Y64h8I",
"userId": "auth0|userHash",
"displayIconId": "683736c62fd7c5cd177d206f",
"url": "https://media-secure.aws.com/icons/mlWc6s-JG",
"new": true
}
}

Now you can use the mediaId whenever you need to reference the animated GIF icon.

  • Keep animations simple and subtle
  • Use a limited color palette so that it displays nicely on your Yoto player
  • Consider the animation speed, too fast can be distracting, and too slow can look laggy

Here’s an example of a complete workflow:

import { readFileSync } from 'node:fs';
export async function createAnimatedGifCard({
iconPath = './animated-icon.gif',
filename = 'animated-icon',
title = 'My Playlist with Animated Icon',
cardId,
accessToken,
}) {
// Read the animated GIF file
// Note: Your GIF must be exactly 16x16 pixels
const gifBuffer = readFileSync(iconPath);
// Create a Blob from the buffer
const gifFile = new Blob([gifBuffer], { type: 'image/gif' });
// Set up the upload URL with required parameters
const url = `https://api.yotoplay.com/media/displayIcons/user/me/upload?autoConvert=false&filename=${filename}`;
console.log('Uploading animated GIF...');
// Upload the file
const uploadResponse = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'image/gif',
},
body: gifFile,
});
if (!uploadResponse.ok) {
const errorText = await uploadResponse.text();
throw new Error(`Upload failed: ${uploadResponse.status} ${errorText}`);
}
const uploadResult = await uploadResponse.json();
// The response should contain the mediaId
const { mediaId } = uploadResult.displayIcon;
console.log('Animated GIF uploaded successfully:', {
mediaId,
});
// Step 2: Create streaming card content using the uploaded animated GIF
// Here, we're making a streaming playlist for simplicity
const chapters = [
{
key: '01',
title: title,
overlayLabel: '1',
tracks: [
{
key: '01',
type: 'stream',
format: 'mp3',
title: title,
trackUrl: 'https://yoto.dev/music/autumn-3.mp3',
display: {
icon16x16: `yoto:#${mediaId}`, // Using the uploaded animated GIF
},
},
],
display: {
icon16x16: `yoto:#${mediaId}`, // Using the uploaded animated GIF
},
},
];
const content = {
title,
content: { chapters },
metadata: {
description: `Streaming card with animated ${filename} icon`,
},
};
if (cardId) {
// specify a cardId to update an existing card
content.cardId = cardId;
}
// Create the card with the animated GIF icon
const createResponse = await fetch('https://api.yotoplay.com/content', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(content),
});
const card = await createResponse.json();
console.log('Streaming card created successfully with animated GIF icon!');
return card;
}