Convert MOV to MP4 with FFmpeg or One API Call
Convert MOV to MP4 with FFmpeg: a fast remux when the codecs allow it, a re-encode for HEVC and ProRes, and the same job as one API call with no FFmpeg install.
To convert a MOV to MP4 with FFmpeg, first check the codecs. If the MOV already has H.264 video and AAC audio, copy the streams into a new container: ffmpeg -i input.mov -c copy -movflags +faststart output.mp4. If it has HEVC, ProRes or another codec, re-encode: ffmpeg -i input.mov -c:v libx264 -crf 23 -pix_fmt yuv420p -c:a aac output.mp4.
This guide explains both paths, how to tell which one you need, and how to do the same job with one Xora API call. For other common commands, see the FFmpeg cheat sheet.
Step 1: Check the codecs
ffprobe -v error -show_entries stream=codec_type,codec_name,pix_fmt -of compact input.mov| What you see | What to do |
|---|---|
h264 video and aac audio | Remux with -c copy. |
hevc video (common from recent iPhones) | Re-encode to H.264 for wide playback. |
prores video (common from cameras and editors) | Re-encode to H.264. |
pcm_s16le or other PCM audio | Re-encode the audio to AAC. |
Step 2a: Remux (no re-encode)
ffmpeg -i input.mov -c copy -movflags +faststart output.mp4-c copy moves the streams into the MP4 unchanged, so there is no quality loss and it runs about as fast as the disk can read. -movflags +faststart puts the index at the start, so a browser can start playback at once.
Step 2b: Re-encode
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset medium -pix_fmt yuv420p -c:a aac -b:a 160k -movflags +faststart output.mp4| Flag | What it does |
|---|---|
-c:v libx264 -crf 23 | Encode H.264 at a good default quality. |
-pix_fmt yuv420p | Convert 10-bit or 4:2:2 sources (HEVC HDR, ProRes) to the pixel format browsers play most reliably. |
-c:a aac -b:a 160k | Encode the audio as AAC. Use -c:a copy if it is AAC already. |
To make the file smaller as well, see how to compress video with FFmpeg.
The same job with the Xora API
The webReady recipe does Step 1 for you. It probes the file, passes it through when it is already fine, remuxes when only the container or index needs to change, and re-encodes only when the codecs do not play in browsers:
{ "mode": "recipe", "input": { "url": "https://example.com/clip.mov" }, "output": { "format": "mp4" }, "recipe": { "name": "webReady" }}To always convert, use the transcode recipe with "output": { "format": "mp4" }, or send your own arguments:
{ "mode": "ffmpeg", "input_files": { "in_1": "https://example.com/clip.mov" }, "output_files": { "out_1": "clip.mp4" }, "ffmpeg": { "args": [ "-i", "{{in_1}}", "-c:v", "libx264", "-crf", "23", "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "160k", "-movflags", "+faststart", "{{out_1}}" ] }}Send the body to https://api.xora.sh/v1/jobs with Authorization: Bearer YOUR_API_KEY, then poll GET /v1/jobs/{id} or pass webhookUrl. A remux uses little machine time, so it costs few credits. See the web-ready and transcode recipes.
Common errors
| Error | Cause | Fix |
|---|---|---|
Could not find tag for codec pcm_s16le | MP4 does not hold that PCM audio. | Re-encode the audio: -c:a aac. |
Could not find tag for codec prores | MP4 does not hold ProRes. | Re-encode the video: -c:v libx264. |
| The MP4 plays without video in a browser | The video is HEVC or 10-bit. | Re-encode with -c:v libx264 -pix_fmt yuv420p. |
| The file is much bigger than the MOV | The CRF is too low for the source. | Raise the CRF to 26 to 28. |
VALIDATION_ERROR (Xora) | A field in the job body is wrong. | Read error.message; it names the field. |
Failed and rejected Xora jobs cost nothing. See error handling.
Related
- How to compress video with FFmpeg.
- Web-ready video: encoding settings that play everywhere.
- FFmpeg cheat sheet.
Frequently asked questions
How do I convert MOV to MP4 with FFmpeg without losing quality?
If the MOV holds H.264 video and AAC audio, use ffmpeg -i input.mov -c copy -movflags +faststart output.mp4. This changes only the container, so there is no quality loss and it finishes quickly. If the codecs are different, the video must be re-encoded.
Why does my converted MP4 not play in the browser?
Usually the video is HEVC (H.265) or ProRes, or it uses a 10-bit or 4:2:2 pixel format. Browsers play H.264 with yuv420p most reliably. Re-encode with -c:v libx264 -pix_fmt yuv420p.
Is MOV or MP4 better?
They are both containers and can hold the same codecs. MP4 is supported by more players, browsers and platforms, so it is the safer choice for sharing and for the web.
Can I convert MOV to MP4 without installing FFmpeg?
Yes. Send the MOV URL to the Xora API with the transcode recipe and output format mp4, or with the webReady recipe, which checks the file first and only re-encodes when it has to.