You may create a shorter file and add zero padding to the end of the file.
The key is to place the "moov atom" at the begging of the file.
Generate synthetic (gray) video using FFmpeg:
ffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=1 -vf hue=s=0 -vcodec libx264 -preset superfast -tune zerolatency -pix_fmt yuv420p -t 1000 -movflags +faststart vid.mp4
You may use Python subprocess module:
sp.run('ffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=1 -vf hue=s=0 -vcodec libx264 -preset superfast -tune zerolatency -pix_fmt yuv420p -t 1000 -movflags +faststart vid.mp4')
Pad file with zeros at the end to make file size exactly 50 MB.
Here is the Python code:
import subprocess as sp
import os
# Generate synthetic pattern.
# Make the pattern gray: https://davidwalsh.name/convert-video-grayscale
# Place the moov atom at the beginning of the file: https://superuser.com/questions/606653/ffmpeg-converting-media-type-aswell-as-relocating-moov-atom
# Use superfast preset and tune zerolatency for all frames to be key frames https://lists.ffmpeg.org/pipermail/ffmpeg-user/2016-January/030127.html (not a must)
# Make the file much smaller than 50MB.
sp.run('ffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=1 -vf hue=s=0 -vcodec libx264 -preset superfast -tune zerolatency -pix_fmt yuv420p -t 1000 -movflags +faststart vid.mp4')
# Add zero padding to the end of the file
# https://stackoverflow.com/questions/12768026/write-zeros-to-file-blocks
stat = os.stat('vid.mp4')
with open('vid.mp4', 'r+') as of:
of.seek(0, os.SEEK_END)
of.write('\0' * (50*1024*1024 - stat.st_size))
of.flush()
In case you want file size to be approximately 50MB, you may set the bitrate and the time.
The size in bits is going to be bitrate*time.
See How to force Constant Bit Rate using FFMPEG
Note: there is a small issue with the test pattern - it is too "compressible", so we need to set a very small bit rate.
Here is an example, creating approximately 1MB MP4 file (10kbit*1024*800/8 = 1MB
):
ffmpeg -y -f lavfi -i testsrc=size=3840x2160:rate=1 -vf hue=s=0 -vcodec libx264 -tune zerolatency -b:v 10k -minrate 10k -maxrate 10k -t 800 -movflags +faststart -bufsize 1024k vid.mp4
Update:
Generating 50MB MP4 file with 5 seconds duration:
Size of 50MB for 5 seconds requires bitrate of about 80,000,000 bis/sec
.
Since the bitrate is very high, we need to use input frame with high resolution and high frame rate.
We also need to make sure that video frames are not well compressed.
Random input images are recommended, because random data is hardly compressible.
The following Python code builds 300 random images in resolution 1920x1080, and encode the images sequence to MP4 video file using FFmpeg:
import numpy as np
import cv2
import subprocess as sp
import os
# Build random input files (set of Tiff images).
# Use random data
# Use Full HD video frames at 60Hz
width, height, fps = 1920, 1080, 60
# Video duration in seconds
n_seconds = 5
for i in range (n_seconds*fps):
# Random gray image in resolution width by height.
img = np.random.randint(0, 255, (height, width), np.uint8)
# Images sequance file names (about 1GBytes of disk space):
# 00000.tif, 00001.tif, 00002.tif, 00003.tif... 00299.tif
cv2.imwrite(str(i).zfill(5)+'.tif', img)
# Destination file size is 50MBytes.
file_size_in_bytes = 50*1024*1024
# Desired bitrate is 83886080*0.90 bits/second
# Multiply by 0.9 - Leave 10% for the headers.
bitrate = int(round(file_size_in_bytes*8*0.9 / n_seconds))
# Encode video from the sequence of random images (use H.264 video codec).
# Set the video bitrate to 75497472.
# Set buffer size to 75497472*10 (not too tight) If we specify a smaller -bufsize, ffmpeg will more frequently check for the output bit rate and constrain it... https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
sp.run('ffmpeg -y -r {} -i %05d.tif -vcodec libx264 -tune zerolatency -b:v {} -minrate {} -maxrate {} -movflags +faststart -bufsize {} vid.mp4'.format(fps, bitrate, bitrate, bitrate, bitrate*10))
The size of vid.mp4
is very close to 50MB.