Dribbble shot video: 20 MB limit and the bitrate budget
Dribbble allows MOV or MP4 video up to 20MB and recommends 1600 px width. What 20MB means in average Mbps by clip length, and which Sume Timeline fields help.

A Dribbble shot video must be MOV or MP4 and at most 20MB, and Dribbble recommends a minimum width of 1600 pixels. Twenty megabytes is a total of 160,000,000 bits, so a 30-second clip averages at most 5.33 Mbps for video and audio together. Sume's Timeline has no bitrate field, so the lever you control is length.
What Dribbble accepts
Dribbble's page says it eased its requirements: there is no longer a fixed ratio or height. The page does not define whether MB means 1,000,000 or 1,048,576 bytes, so the table shows both.
| Content | Types | Maximum | Recommended |
|---|---|---|---|
| Image | png, jpg, gif | 10MB | width of at least 1600 px |
| Video | mov, mp4 | 20MB | width of at least 1600 px |
The bitrate budget
Average total bitrate is the cap in bits divided by the clip length in seconds. Anything above the average will overshoot unless the encoder lowers it elsewhere.
| Clip length | If MB = 1,000,000 bytes | If MB = 1,048,576 bytes |
|---|---|---|
| 15 s | 10.67 Mbps | 11.18 Mbps |
| 30 s | 5.33 Mbps | 5.59 Mbps |
| 60 s | 2.67 Mbps | 2.80 Mbps |
| 90 s | 1.78 Mbps | 1.86 Mbps |
| 120 s | 1.33 Mbps | 1.40 Mbps |
What Sume lets you control
Timeline 1.0 takes output width and height as even integers from 256 to 2160, so 1600x900 is a legal frame. It also takes output.fps of 24, 25, 30 or 60. It rejects codec, crf and other encoder keys with a 400, so you cannot set a target bitrate.
The unbilled plan route returns duration, segment count, billable minutes and estimated cost, but no file size. So render, download and measure. Timeline costs $0.10 per output minute rounded up, so a clip under a minute costs $0.10. If the file is over, cut length with video trim, which costs $0.02 per job.
Budget and check script
import asyncio, os
DECIMAL = 20 * 1_000_000
BINARY = 20 * 1024 * 1024
def mbps(seconds, cap):
return cap * 8 / seconds / 1_000_000
async def main():
for seconds in (15, 30, 60, 90, 120):
print(seconds, round(mbps(seconds, DECIMAL), 2), round(mbps(seconds, BINARY), 2))
path = "shot.mp4"
if os.path.exists(path):
size = os.path.getsize(path)
print(path, size, "ok" if size <= DECIMAL else "over the 20MB reading")
asyncio.run(main())Before you upload
- Frame is at least 1600 px wide.
- File measured with the decimal reading, 20,000,000 bytes, to be safe.
- Keep a shorter cut ready if the render lands over.
Sources
Related posts
More in Use cases
- eBay AI listing photos: the seller owns accuracy
eBay's User Agreement makes sellers responsible for listing accuracy, including generative AI content. Generate 1:1 stills from your real photo and check them.
- E-commerce product video cost per SKU: cutout plus a 5-second clip
A cutout at $0.0225 plus a 5-second 720p Seedance 2.5 clip is $2.9115 per SKU on Sume. For 100 SKUs that is $291.15. Arithmetic inside.
- ElevenLabs free-plan music: the ElevenMusic credit rule for ads
Free ElevenLabs users may use tracks commercially only with an ElevenMusic credit; Pro gets rights with the plan. What that means for a paid video ad.
- Estate sale preview video from mixed portrait and landscape photos
Phone photos of estate sale lots come in both orientations. Timeline's fit modes (cover, contain, stretch, blur) decide whether a lot is cropped or kept whole.
Written by Sume