ffmpegtranscodingapi

Transcode H265 to H264 without installing a converter

··10 min read
Transcode H265 to H264 without installing a converter

To transcode H265 to H264, run ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -pix_fmt yuv420p -c:a aac -b:a 192k output.mp4. That command decodes the HEVC video and re-encodes it as H.264 in an MP4, which is what social platforms, browsers and most editors accept. You cannot do this with a stream copy, because H.265 and H.264 are different codecs and -c copy only changes the container. The same job runs as one API call when the machine in your pipeline has no FFmpeg on it.

Search for this task and the first page is desktop software: a file picker, a dropdown, one file at a time, a human clicking Convert. That's a fine answer if you have one wedding video. It's the wrong answer if you have a Dropbox folder of drone footage, an n8n branch that fires on every new upload, or a queue that accepts whatever a customer hands you. The job isn't "pick a converter." The job is "make every HEVC file that arrives come out as H.264 at a spec a platform will accept, without anybody watching."

Why your footage keeps arriving as HEVC

HEVC shows up because the devices recording video default to it. Apple's iPhone records in HEVC when the camera format is set to High Efficiency, and Apple's own support page describes Most Compatible as the opt-out that gives you H.264 instead. DJI lists both MPEG-4 AVC/H.264 and HEVC/H.265 among its supported recording codecs, and pilots on DJI's forum report modes where H.265 is the only option. Screen recorders and a growing share of AI video tools hand back HEVC for the same reason: roughly half the bitrate for the same picture.

The delivery side moved in the opposite direction. H.264 has effectively universal browser support while HEVC support is partial or off by default in Chrome and Firefox. Playing HEVC on Windows can require the HEVC Video Extensions package from the Microsoft Store, which is a paid app unless the hardware vendor shipped a licensed copy. The licensing picture explains the gap: HEVC royalties are split across multiple pools with per-unit device fees and a rate increase for new licensees from January 2026, while H.264 licenses through one. NetInt's 2026 survey of 286 video professionals found H.264 still at 84% production adoption, against 17% for AV1.

The gap between what cameras record and what distribution accepts holds steady, so the compatibility transcode is a standing step in any pipeline taking in outside footage.

A stream copy can't do this, and the error tells you why

-c copy moves streams into a new container without touching them, so copying HEVC into an MP4 gives you an MP4 that still contains HEVC. No error, no warning, and the platform on the far end rejects it anyway. Copy that same stream into a container with no HEVC mapping and FFmpeg says it out loud: Could not find tag for codec hevc in stream #0, codec not currently supported in container.

MP4 happily carries H.265. The container was never the problem. The decoder on the other end is.

One case where a remux really is the fix: if your HEVC file plays in VLC but shows nothing in QuickTime or Finder, FFmpeg probably tagged it hev1, and Apple's AVFoundation only decodes hvc1. ffmpeg -i in.mp4 -c copy -tag:v hvc1 out.mp4 fixes that in seconds with no re-encode. That's a different problem, worth ruling out before you spend an encode on it.

The flags that decide whether the output passes

Each setting in the command above does specific work, and the defaults are documented. According to FFmpeg's H.264 encoding guide, CRF 23 is libx264's default on a 0 to 51 scale where lower is better quality, and medium is the default preset. Preset changes how long the encode takes and how efficiently it uses bits.

FlagWhat it controlsSane default
`-c:v libx264`The video encoder, the whole point of the jobrequired
`-crf 23`Quality target; 18 for near-transparent, 28 for small23
`-preset medium`Encode speed vs compression efficiencymedium
`-pix_fmt yuv420p`8-bit 4:2:0, forces High profile instead of High 10required for handoff
`-c:a aac -b:a 192k`Audio to AAC, since HEVC files often carry AAC already but not always192k stereo

The destination has opinions about all of this. X's media best practices require H.264 High Profile video, AAC LC audio, YUV 4:2:0 as the only supported pixel format, progressive scan and no open GOP. A non-conforming master gets rejected, not fixed for you. We went through the rest of that spec in X (Twitter) video specs that survive the upload (and the API).

8-bit or 10-bit: which one your destination can decode

The pixel format you pick decides which H.264 profile you land in, and 8-bit 4:2:0 is the one every destination outside your own pipeline can handle. If your source is 10-bit HEVC, which is what a modern drone and a lot of phone HDR footage produce, re-encoding without -pix_fmt yuv420p gives you 10-bit H.264 in High 10 profile. VLC plays it because VLC uses FFmpeg's decoder. QuickTime, Premiere, browsers and platform upload validators often won't, because many non-FFmpeg players cannot decode H.264 with anything other than 4:2:0 8-bit chroma. A libx264 build encodes 8-bit or 10-bit, not both in one command.

The Academy Software Foundation's H.264 encoding guidelines pin both the profile and the pixel format explicitly instead of letting the encoder pick. For anything you're handing to another system, add -pix_fmt yuv420p and stop guessing. Going to 8-bit is the wrong call for a file headed back into a grading timeline or an HDR master. Keep that copy in 10-bit and encode a separate 8-bit delivery file. A related version of this trap, where the picture survives but the color tag doesn't, shows up in Kling 4.0 washed out on TikTok?.

The same transcode as one API call

Everything above assumes FFmpeg is installed on the machine doing the work, which is the one assumption that fails for an n8n or Make builder, a serverless function, or a locked-down host. The usual workaround is a shell or PowerShell loop over a folder, which means somebody has to own an FFmpeg build and keep it patched.

The pipeline version is a job you submit and poll. Check the codec first so you only pay for the files that actually need converting:

curl -X POST https://api.ffmpeg-micro.com/v1/ffprobe \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"media_url": "gs://your-bucket/DJI_0042.MP4"}'
# streams[0].codec_name == "hevc"  => transcode it
# streams[0].codec_name == "h264"  => skip, it already conforms

Then submit the transcode, poll, and pull the file:

# create the job
JOB=$(curl -s -X POST https://api.ffmpeg-micro.com/v1/transcodes \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"inputs":[{"url":"gs://your-bucket/DJI_0042.MP4"}],
       "outputFormat":"mp4",
       "preset":{"quality":"medium","resolution":"1080p"}}' | jq -r '.id')

# poll until completed or failed
curl -s "https://api.ffmpeg-micro.com/v1/transcodes/$JOB" \
  -H "Authorization: Bearer $API_KEY" | jq -r '.status'

# get a signed download URL (valid 10 minutes)
curl -s "https://api.ffmpeg-micro.com/v1/transcodes/$JOB/download" \
  -H "Authorization: Bearer $API_KEY" | jq -r '.url'

That's four requests you can wrap in a for loop over a folder, or three HTTP Request nodes in an n8n branch that fires per file. FFmpeg Micro runs the encode on managed workers, so there's no binary to install and nothing to babysit when a 4K master takes nine minutes. PHP and Python SDKs wrap the same endpoints; from Node or n8n you call the REST API directly, which matters more now that n8n 3.0 disables community nodes by default.

The economics are the part that changes how you batch. Billing is on the duration of the input video, metered per second with no rounding up to the minute, and failed jobs are never billed. One token buys 10 seconds of input. So 40 clips of 30 seconds each costs 120 tokens whether x264 chewed through them at veryslow or ultrafast, and a 30-second trim out of a one-hour recording is billed as 30 seconds.

When to convert, and when to leave the HEVC alone

Transcode when the file is leaving your control: a platform upload, a browser player, a customer download, or an editor that chokes on HEVC. Those destinations publish a spec, and H.264 High Profile 4:2:0 in MP4 is the intersection of every one of them.

Don't transcode in these cases:

  • You're archiving the master. Re-encoding is lossy, and HEVC at half the bitrate is the better thing to keep. Transcode a delivery copy, keep the original.
  • You're grading or finishing 10-bit HDR. Going to 8-bit 4:2:0 throws away the color data the grade needs.
  • The destination genuinely wants HEVC. Apple-ecosystem delivery and some CDNs prefer it, so the right fix might be the hvc1 tag instead.
  • You need an adaptive ladder with HLS packaging and a player. That's a managed streaming pipeline's job, not a single-output transcode, and one MP4 won't get you there.

Two limits worth knowing before you batch. The free tier caps input files at 100 MB, which a two-minute 4K HEVC drone clip will exceed; Starter at $19.99 a month raises that to 1,024 MB and Pro at $49.99 to 2,048 MB. And a transcode is still an encode, so quality is a choice you make with CRF, not something the API guesses for you.

FAQ about transcoding H.265 to H.264

Does a slower FFmpeg preset cost me more money?

A slower preset costs more wall-clock time and gives slightly better compression at the same CRF. On FFmpeg Micro it costs no extra money, because billing is on the input video's duration rather than on how long the encode ran. On meters that charge per conversion-minute or per GPU-second, a slower preset does cost more.

How do I convert a whole folder of HEVC files at once?

Loop over the folder and submit one job per file: probe the codec, skip anything already H.264, submit the rest, poll each job ID, download the outputs. Builders who do this locally usually end up writing shell or PowerShell loops around FFmpeg, as the threads on VideoHelp show; the API version replaces the binary and the loop still belongs to you.

Why does my converted file play in VLC but not in QuickTime?

A file that plays in VLC and fails elsewhere is almost always 10-bit H.264 in High 10 profile, produced by re-encoding a 10-bit HEVC source without -pix_fmt yuv420p. VLC decodes it through FFmpeg's decoder; QuickTime and browser decoders generally do not. Re-encode with -pix_fmt yuv420p to land in High profile.

Can I convert HEVC to H.264 from n8n, Make or Zapier?

n8n, Make and Zapier can all do this by calling a video API over HTTP instead of running FFmpeg, because none of those platforms let you install an encoder on the worker. The pattern is an HTTP Request node that submits the job, a short wait, a second node that polls status, and a third that fetches the signed download URL.

What happens if the transcode fails halfway?

A failed transcode moves the job status to failed and you are not billed for it. Corrupt input, an unsupported codec inside a mislabeled container, and a file over your plan's input cap are the three common causes, and running ffprobe first catches the first two before you spend anything.

Two hundred tokens come with a new account at no cost and no card, which is about 33 minutes of footage, enough to run a typical week's drone or phone dump through the loop above. Sign up free and point it at the worst file you have: no servers to run, no FFmpeg to install, callable from your own code, from n8n, Make and Zapier, or from your AI agents.

About Javid Jamae

Founder & CEO at FFmpeg Micro

Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free