Intro Makers

YouTube End Screen Template [2026]: 12 Steps, 25 Min

YouTube End Screen Template [2026]: 12 Steps, 25 Min

A YouTube end screen only works if your video leaves room for it. YouTube’s own Help page says an end screen can sit in the last 5 to 20 seconds of a video, the video must run at least 25 seconds, and a standard 16:9 video can hold up to four elements. Those three numbers decide how you design an outro, so this tutorial builds the whole youtube end screen template around them: YouTube’s end screen rules first, pretty graphics second.

By the end you will have a reusable 20-second outro template at 1920×1080, a 4-second logo intro, a script that glues both onto any 16:9 video using YouTube’s recommended upload settings, and a checker that tells you whether the finished file can take an end screen. Everything runs from a terminal, and every file is printed in full below.

Short on time? Steps 5 to 8 produce the outro itself. If you would rather skip the terminal and build the same layout in an editor, the no-code section near the end maps each step onto a timeline. For other formats in the same family, the Intro Makers hub collects our guides on intros, outros and stings.

What a YouTube outro and an end screen actually are

An outro is footage you edit into the end of your video. An end screen is a set of clickable elements YouTube draws over the last seconds of that footage. They are two different things that need to line up. The outro is the picture, the end screen is the buttons, and YouTube only controls the buttons.

That split matters because YouTube does not read your outro. It has no idea where you left empty space. You tell it where to put the elements in YouTube Studio, and if your outro art sits underneath them, the viewer sees a clutter of overlapping graphics. A good youtube outro template is really a map of empty slots with a tidy frame around each one.

The rules below come from YouTube’s Help page on adding end screens, which is the vendor source for every limit in this section. Treat them as the spec for the template you are about to build.

RuleWhat YouTube statesWhat it means for your template
Minimum video lengthAt least 25 secondsMain video plus outro must reach 25 s or more
Timing windowThe last 5 to 20 secondsBuild a 20 s outro so the window is fully used
Element limit (16:9)Up to four elementsDesign three or four slots, never five
Other aspect ratiosMay have a lower limitKeep to 16:9 if you want the full four
Element typesVideo, playlist, subscribe, channel promotionPlan slots for the types you will actually use
External linksYouTube Partner Program members onlyDo not reserve a slot for a link unless you qualify
Not eligibleMade for kids, YouTube Music app, YouTube Kids app, 360 videos, mobile web (iPad excepted)Check your video type before designing anything
Side effectsCard teasers and video watermarks are suppressed during the end screenDo not rely on a corner watermark in the outro
Viewer controlViewers can hide end screensNever put essential information only under an element

One line in that table deserves a second look: viewers can hide end screens. Your outro should still make sense as plain video with nothing on top. That is why the template in this tutorial carries a headline and frames, so it never looks broken when the buttons are hidden.

How long should a YouTube intro and outro be

YouTube sets a hard rule for end screens (5 to 20 seconds, 25 second minimum) and, in the Help pages read for this guide, no rule for intro length. So the numbers in this section are editorial recommendations from this kit, not platform requirements. Use them as defaults, then adjust to your channel.

Intro length: shorter than you think

Aim for a logo sting of 3 to 5 seconds, and cut anything past 6. The kit below defaults to 4 seconds. A viewer who clicked a thumbnail wants the first thing the thumbnail promised, so the intro should either follow a hook or be short enough that nobody notices it.

A workable pattern: open on the hook line for 5 to 15 seconds, then play the 4-second sting, then continue. Channels that put the sting before any content ask the viewer to wait for branding they did not request. If you cannot tell which order suits your channel, open the audience retention graph in YouTube Studio and look at the first 30 seconds to see where viewers leave.

Outro length: use the window, not more

For the outro, 20 seconds is the practical ceiling because the end screen cannot start earlier than 20 seconds from the end. Anything you render beyond 20 seconds plays without clickable elements on the first stretch. The kit defaults to exactly 20 seconds so the full window is available and the layout never changes.

If your content ends with a spoken sign-off, overlap it. Let the last sentence play over the first 3 or 4 seconds of the outro background so the video does not feel like it stopped and restarted. The timeline table later shows how the build script paces the 20 seconds.

The 25-second floor

Because the video must be at least 25 seconds long, a 20-second outro on a very short clip leaves only 5 seconds of real content. That ratio feels wrong to viewers. For anything under about a minute, a trimmed 8 to 10 second outro often works better, and you set the end screen to start for however long you kept. Change the duration value in the layout file (introduced below) and the rest of the kit follows.

Prerequisites and tools

You need a terminal, three small tools, and one finished video to test with. Nothing here is paid, and none of it needs an account except YouTube Studio itself.

ToolVersionWhy you need itFree plan
FFmpeg and ffprobeCurrent stable release built with libx264 and libfreetypeRenders the intro and outro, joins clipsFree, open source
Python3.7 or newer (the checker uses capture_output)Builds the filter chain and checks filesFree, open source
BashAny recent version (Linux, macOS, or WSL on Windows)Runs the assemble and intro scriptsIncluded with the OS
YouTube StudioCurrent web versionPlaces the end screen elementsEnd screens are built in, external links need Partner Program
Logo filePNG with transparency, at least 720 px wideUsed in the 4-second introYour own asset

Confirm your FFmpeg build before going further. Run ffmpeg -version and look for --enable-libx264 and --enable-libfreetype in the configuration line. The first is needed for H.264 output and the second for the drawtext filter. Many package-manager builds include both. If yours does not, the troubleshooting section covers the exact error you will see.

You also need a font. The scripts default to DejaVu Sans Bold at /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf, which ships with many Linux installs. On macOS or Windows, point the OUTRO_FONT environment variable at any TTF file you own.

Make a working folder and put your test video in it:

mkdir outro-kit && cd outro-kit
ffmpeg -version | head -n 1
ffprobe -version | head -n 1
python3 --version

Render settings

Every file in this kit follows YouTube’s recommended upload encoding settings, so the finished video matches what the platform asks for. The table lists what the kit produces and where each value comes from.

SettingValue used in this kitSource
Resolution1920×1080 (16:9)YouTube’s resolution and aspect ratio page lists 1080p as 1920×1080
Frame rateMatch your recording, outro built at 30 fpsYouTube advises uploading at the recorded frame rate
ContainerMP4 with the moov atom at the front (fast start)YouTube upload encoding settings
Video codecH.264, High profile, 2 B-frames, closed GOP at half the frame rateYouTube upload encoding settings
Video bitrate8 Mbps for 1080p at 24, 25 or 30 fpsYouTube’s SDR bitrate table
Color spaceBT.709YouTube recommends it for SDR uploads
Audio codecAAC-LCYouTube upload encoding settings
Audio sample rate48 kHzYouTube upload encoding settings
Audio bitrate384 kbps for stereoYouTube upload encoding settings
Outro length20 secondsThe end screen window
Intro length4 secondsThis kit’s default, not a YouTube rule

For reference, the same bitrate table lists 5 Mbps for 720p, 16 Mbps for 1440p and 35 to 45 Mbps for 4K at standard frame rates. If you work in 4K, scale the template coordinates by two and raise the bitrate to the 4K figure. The layout logic does not change.

One more format note. YouTube’s aspect ratio page says the standard ratio on a computer is 16:9 and that vertical 9:16 video can get extra padding in a desktop browser. It also advises against adding your own padding or black bars. This kit assumes 16:9 throughout. A vertical video can still carry an end screen, but the Help page warns the element limit may be lower, so check Studio for what you get.

Project layout and the end screen template file

The kit has six files. You will create them one at a time as you work through the steps.

FileRole
layout.jsonCanvas size, colors, headline and the slot rectangles
build_outro.pyTurns the layout into an FFmpeg command and runs it
make_intro.shRenders the 4-second logo intro
assemble.shJoins intro, main video and outro with YouTube’s settings
check_outro.pyVerifies the finished file against the end screen rules
main.mp4Your own finished video (you supply this)

The heart of the project is layout.json. It stores where each end screen element will sit, so the outro art and your Studio placement come from one source of truth. Everything is in pixel coordinates on a 1920×1080 canvas.

{
  "canvas": { "w": 1920, "h": 1080, "fps": 30, "duration": 20 },
  "colors": { "bg": "0x101820", "accent": "0xFFC400" },
  "headline": "Watch next",
  "slots": [
    { "name": "video_a",   "x": 120,  "y": 330, "w": 800, "h": 450 },
    { "name": "video_b",   "x": 1000, "y": 330, "w": 800, "h": 450 },
    { "name": "subscribe", "x": 860,  "y": 820, "w": 200, "h": 200 }
  ]
}

Both video slots use 800×450, which is exactly 16:9, so a video element’s thumbnail fills the frame without cropping. The subscribe slot is a 200×200 square because the button is round and square space is the easiest to reason about. Three slots leave one of the four allowed elements free. Keep it free for now. You can add a playlist or channel promotion later without redesigning anything.

Steps 1 to 4: plan the outro before you build it

Planning a YouTube end screen template takes ten minutes and saves hours of re-rendering. These four steps are decisions, not commands, and the layout file from the previous section holds the results.

Step 1: Decide what the viewer should do next. Pick one primary action. For most channels it is “watch the next video.” Subscribe is secondary. Two video slots plus a subscribe button gives the viewer a clear first choice and a clear second one. If you have a series, make video slot A the next episode and slot B a best-performing older video.

Step 2: Check eligibility. Before you design anything, confirm the video is not set as made for kids and is not a 360 video. The Help page also lists the YouTube Music app, the YouTube Kids app and mobile web (iPad excepted) as places where end screens do not apply. If your content falls in that group, this tutorial’s outro still works as plain footage, but the clickable layer will not appear.

Step 3: Choose the slot count. Count the elements you will actually fill. The limit of four for 16:9 video is a ceiling, not a target. Three slots read cleanly at 1080p. Four slots are possible, but each tile shrinks and the thumbnails turn into postage stamps on a phone.

Step 4: Lay out the canvas with margins. Leave at least 60 px of margin around every slot edge. The frames in layout.json are drawn 12 px outside each slot, so a 60 px margin keeps them well clear of the canvas edge. Put the headline above the slots, at roughly 120 px from the top, where no element will sit. Keep the bottom of the frame clear of text because players overlay a progress bar there.

The timeline for the 20 seconds is also a plan worth writing down. This is the schedule the build script follows.

Time in outroWhat happensWhy
0.0 to 0.5 sFade in from blackSoft join after your last sentence
0.3 sHeadline appearsGives the eye an anchor before the frames
0.8 sSlot frames appearFrames show where the elements will land
0.8 to 19.5 sFrames and headline holdSteady layout while the viewer decides
19.5 to 20.0 sFade outClean exit if autoplay is off

Steps 5 to 8: build and render the outro

These steps produce the actual YouTube outro template render. The only input is layout.json, so changing the design later means editing JSON and re-running one command.

Step 5: Save the layout file. Create layout.json with the content shown in the previous section. Check that it parses before moving on:

python3 -c "import json; json.load(open('layout.json')); print('layout ok')"

Step 6: Save the build script. The script reads the layout, builds the FFmpeg filter chain and runs the render. It also has a --print flag that shows the command without running it, which makes debugging much easier, and a --guide flag that labels every slot so you can check placement.

#!/usr/bin/env python3
import json
import os
import subprocess
import sys
from pathlib import Path

FONT = os.environ.get("OUTRO_FONT", "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf")


def build(layout, guide, music):
    c, col = layout["canvas"], layout["colors"]
    w, h, fps, dur = c["w"], c["h"], c["fps"], c["duration"]
    f = ["format=rgb24"]
    f.append(
        f"drawtext=fontfile={FONT}:text='{layout['headline']}':fontcolor=white:"
        f"fontsize=96:x=(w-text_w)/2:y=120:enable='gte(t,0.3)'"
    )
    for s in layout["slots"]:
        f.append(
            f"drawbox=x={s['x'] - 12}:y={s['y'] - 12}:w={s['w'] + 24}:h={s['h'] + 24}:"
            f"color={col['accent']}@0.9:t=6:enable='gte(t,0.8)'"
        )
        if guide:
            f.append(
                f"drawtext=fontfile={FONT}:text='{s['name']}':fontcolor=white:fontsize=30:"
                f"x={s['x']}:y={s['y'] + s['h'] + 24}"
            )
    f.append(f"fade=t=in:st=0:d=0.5,fade=t=out:st={dur - 0.5}:d=0.5")
    f.append("scale=out_color_matrix=bt709:out_range=tv,format=yuv420p")

    cmd = ["ffmpeg", "-y", "-f", "lavfi", "-i", f"color=c={col['bg']}:s={w}x{h}:r={fps}:d={dur}"]
    if music:
        cmd += ["-i", music]
        af = f"aresample=48000,afade=t=in:st=0:d=1,afade=t=out:st={dur - 2}:d=2"
    else:
        cmd += ["-f", "lavfi", "-i", "anullsrc=r=48000:cl=stereo"]
        af = "anull"
    cmd += [
        "-vf", ",".join(f), "-af", af, "-t", str(dur),
        "-c:v", "libx264", "-profile:v", "high", "-bf", "2", "-g", str(fps // 2),
        "-x264-params", "open-gop=0", "-b:v", "8M", "-pix_fmt", "yuv420p",
        "-color_primaries", "bt709", "-color_trc", "bt709", "-colorspace", "bt709",
        "-c:a", "aac", "-b:a", "384k", "-ar", "48000", "-ac", "2",
        "-movflags", "+faststart",
        "outro_guide.mp4" if guide else "outro.mp4",
    ]
    return cmd


if __name__ == "__main__":
    args = sys.argv[1:]
    layout = json.loads(Path("layout.json").read_text())
    music = args[args.index("--music") + 1] if "--music" in args else None
    cmd = build(layout, "--guide" in args, music)
    if "--print" in args:
        print(" ".join(f'"{p}"' if " " in p or "," in p else p for p in cmd))
    else:
        subprocess.run(cmd, check=True)

A few choices in that script are worth explaining. The graphics are drawn in RGB (format=rgb24) and converted to YUV at the very end with the BT.709 matrix, which keeps the colors matching the BT.709 tags written into the file. The GOP is set to half the frame rate (-g 15 at 30 fps) with open-gop=0 for a closed GOP, and -bf 2 gives the two B-frames. Those mirror YouTube’s recommended settings. The bitrate of 8 Mbps is the table value for 1080p at 30 fps or lower.

Step 7: Render the guide version first. Always look at the labeled version before the clean one. It costs one command and shows immediately whether a slot is crowding another.

python3 build_outro.py --guide

Open outro_guide.mp4 in any player and pause around the 2 second mark. You should see the headline centered near the top, two wide frames side by side, one square frame centered underneath, and a text label under each. If a label runs off the bottom, shrink the slot or move it up in layout.json.

Step 8: Render the clean outro. When the guide looks right, run the same script without the flag. Add --music with a path if you have a licensed track, and make sure you have the rights to use it on YouTube.

python3 build_outro.py
# with music (use only audio you are licensed to publish)
python3 build_outro.py --music my-track.wav
ls -lh outro.mp4

Without music the outro carries a silent stereo track. That is deliberate. Joining clips in a later step fails if one has no audio stream, so a silent track is safer than none. Flat colors compress well, so expect a small file. If outro.mp4 comes out huge, something is wrong with the bitrate arguments.

Steps 9 to 12: join, check, upload and place the elements

The remaining steps turn the template into a finished upload and then, in YouTube Studio, make it clickable.

Step 9: Build the 4-second logo intro. This is optional, and you can skip to Step 10 without it. The script centers your logo at 360 px tall on the same dark background, fades it in over 0.6 seconds and out over the last 0.6 seconds, and adds a silent audio track so it joins cleanly.

#!/usr/bin/env bash
set -euo pipefail

LOGO="${1:?usage: make_intro.sh logo.png [intro.mp4]}"
OUT="${2:-intro.mp4}"

ffmpeg -y \
  -f lavfi -i "color=c=0x101820:s=1920x1080:r=30:d=4" \
  -loop 1 -framerate 30 -t 4 -i "$LOGO" \
  -f lavfi -i "anullsrc=r=48000:cl=stereo" \
  -filter_complex "[1:v]scale=-2:360,format=rgba,fade=t=in:st=0:d=0.6:alpha=1,fade=t=out:st=3.4:d=0.6:alpha=1[logo];[0:v][logo]overlay=(W-w)/2:(H-h)/2:format=rgb,scale=out_color_matrix=bt709:out_range=tv,format=yuv420p[v]" \
  -map "[v]" -map 2:a -t 4 \
  -c:v libx264 -profile:v high -bf 2 -g 15 -x264-params open-gop=0 -b:v 8M \
  -color_primaries bt709 -color_trc bt709 -colorspace bt709 \
  -c:a aac -b:a 384k -ar 48000 -movflags +faststart "$OUT"

Run it with bash make_intro.sh logo.png. A logo with transparency works best. A logo with a solid white box around it will show that box on the dark background, so export from your design tool with the background removed.

From the Vipid archive: if you would rather start from a finished animated sting, the original intro themes list resolution, length and frame rate for each style, which makes them easy to compare against the 4-second default here.

Step 10: Assemble the final video. This script joins the optional intro, your main video and the outro. It reads the frame rate of your main video and converts the other clips to match, because YouTube’s advice is to upload at the frame rate you recorded. It also computes the closed GOP length as half the frame rate.

#!/usr/bin/env bash
set -euo pipefail

MAIN="${1:?usage: assemble.sh main.mp4 [outro.mp4] [final.mp4] [intro.mp4]}"
OUTRO="${2:-outro.mp4}"
OUT="${3:-final.mp4}"
INTRO="${4:-}"

FPS=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of csv=p=0 "$MAIN")
GOP=$(awk -F/ '{ printf "%d", ($1 / $2) / 2 }' <<< "$FPS")

INPUTS=()
FC=""
N=0

add() {
  INPUTS+=(-i "$1")
  FC+="[$N:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,fps=$FPS,setsar=1,format=yuv420p[v$N];"
  FC+="[$N:a]aresample=48000,aformat=channel_layouts=stereo[a$N];"
  N=$((N + 1))
}

if [ -n "$INTRO" ]; then add "$INTRO"; fi
add "$MAIN"
add "$OUTRO"

CHAIN=""
for ((i = 0; i < N; i++)); do CHAIN+="[v$i][a$i]"; done
FC+="${CHAIN}concat=n=$N:v=1:a=1[v][a]"

ffmpeg -y "${INPUTS[@]}" -filter_complex "$FC" -map "[v]" -map "[a]" \
  -c:v libx264 -profile:v high -bf 2 -g "$GOP" -x264-params open-gop=0 -b:v 8M \
  -color_primaries bt709 -color_trc bt709 -colorspace bt709 \
  -c:a aac -b:a 384k -ar 48000 -movflags +faststart "$OUT"

Run it with bash assemble.sh main.mp4 outro.mp4 final.mp4 intro.mp4, or leave off the last argument for no intro. The padding step only matters if your source is not 16:9. For true 16:9 footage it changes nothing, and YouTube’s own advice is to avoid adding bars yourself, so shoot and export in 16:9.

Step 11: Check the file against the rules. The checker reads the output with ffprobe and prints PASS or FAIL for each requirement that decides whether the end screen can work. It also tells you where the 20-second window opens, which is the number you need in Studio.

#!/usr/bin/env python3
import json
import struct
import subprocess
import sys


def probe(path):
    out = subprocess.run(
        ["ffprobe", "-v", "error", "-print_format", "json", "-show_format", "-show_streams", path],
        capture_output=True, text=True, check=True,
    ).stdout
    return json.loads(out)


def faststart(path):
    with open(path, "rb") as fh:
        while True:
            head = fh.read(8)
            if len(head) < 8:
                return False
            size, kind = struct.unpack(">I4s", head)
            if kind == b"moov":
                return True
            if kind == b"mdat":
                return False
            if size == 1:
                size = struct.unpack(">Q", fh.read(8))[0]
                fh.seek(size - 16, 1)
            elif size == 0:
                return False
            else:
                fh.seek(size - 8, 1)


def main(path):
    info = probe(path)
    v = next(s for s in info["streams"] if s["codec_type"] == "video")
    a = next((s for s in info["streams"] if s["codec_type"] == "audio"), None)
    dur = float(info["format"]["duration"])
    checks = [
        ("length is 25 s or more", dur >= 25),
        ("MP4 container", "mp4" in info["format"]["format_name"]),
        ("H.264 video", v["codec_name"] == "h264"),
        ("16:9 frame", v["width"] * 9 == v["height"] * 16),
        ("has an audio track", a is not None),
        ("audio at 48 kHz", a is not None and a.get("sample_rate") == "48000"),
        ("moov atom before mdat", faststart(path)),
    ]
    for label, ok in checks:
        print(("PASS  " if ok else "FAIL  ") + label)
    start = max(dur - 20, 0)
    print(f"duration {dur:.2f} s, end screen window opens at {int(start // 60)}:{start % 60:05.2f}")
    return 0 if all(ok for _, ok in checks) else 1


if __name__ == "__main__":
    sys.exit(main(sys.argv[1]))

Run python3 check_outro.py final.mp4. The faststart function walks the top-level MP4 boxes and reports whether the moov box comes before mdat, which is what the fast-start flag does. The FFmpeg commands in this kit need a run on your own footage, so treat your first render as the real test and read the checker output closely.

Step 12: Upload and place the elements in YouTube Studio. Upload final.mp4 as normal. Then open YouTube Studio and follow the path the Help page gives: Content, pick the video, Editor, End screen. Add your elements one by one:

  • Add a video element and choose the most recent upload, the best one for the viewer, or a specific video.
  • Add a second video element, or a playlist if you prefer to send viewers into a series.
  • Add a subscribe element.
  • Move each element onto its frame from the guide render, matching your layout file by eye.
  • Set the elements to appear when the outro begins, which is 20 seconds before the end, then save.

Free plan line for this step: the Help page restricts only external link elements to YouTube Partner Program members, so video, playlist, subscribe and channel elements are the ones to build around if you are not in the program yet.

Output examples

Knowing what a good run looks like helps you spot a bad one quickly, and the checker gives your YouTube end screen template a clear pass or fail. Here is the checker output you should expect for a 60-second main video with the 20-second outro attached. The numbers follow from the arithmetic, since 60 plus 20 is 80 and the window opens 20 seconds before the end.

$ python3 check_outro.py final.mp4
PASS  length is 25 s or more
PASS  MP4 container
PASS  H.264 video
PASS  16:9 frame
PASS  has an audio track
PASS  audio at 48 kHz
PASS  moov atom before mdat
duration 80.00 s, end screen window opens at 1:00.00

If you added the 4-second intro as well, the duration reads 84.00 and the window opens at 1:04.00. A failing run names the broken rule. This one shows a file that was exported without fast start:

$ python3 check_outro.py broken.mp4
PASS  length is 25 s or more
PASS  MP4 container
PASS  H.264 video
PASS  16:9 frame
PASS  has an audio track
PASS  audio at 48 kHz
FAIL  moov atom before mdat
duration 80.00 s, end screen window opens at 1:00.00

For a deeper look at the stream details you can ask ffprobe directly. These are the values the kit is set up to produce, and they mirror the render settings table:

ffprobe -v error -select_streams v:0 \
  -show_entries stream=codec_name,profile,width,height,r_frame_rate,pix_fmt,color_space \
  -of default=nw=1 final.mp4

You should see codec_name=h264, profile=High, width=1920, height=1080, a frame rate that matches your recording, pix_fmt=yuv420p and color_space=bt709. If color_space comes back unknown, the tagging flags were dropped somewhere, usually by a re-encode in another tool.

Common pitfalls

These are the mistakes that cost creators the most time. Each one has a one-line fix.

  1. Designing for five elements. The limit for a 16:9 video is four, and other aspect ratios may allow fewer. Plan three or four slots and no more.
  2. Starting the outro too late. A 12-second outro can only host an end screen for 12 seconds. If you want the full 20, render a 20-second outro.
  3. Putting key text under an element. Elements cover whatever is below them, and viewers can hide the whole layer. Keep calls to action in the audio and in the headline, not buried under a button.
  4. Mixing frame rates. Gluing a 30 fps outro onto a 60 fps video without conversion makes the outro stutter. The assemble script converts to the main video’s rate for this reason.
  5. Forgetting the 25-second minimum. A 10-second clip with a 20-second outro is 30 seconds and passes, but a 4-second clip with an 8-second outro is 12 and does not. Always run the checker.
  6. Leaving out fast start. YouTube’s encoding page asks for the moov atom at the front of the file. The +faststart flag handles it and the checker flags a miss.
  7. Relying on a watermark. The Help page says video watermarks and card teasers are suppressed during the end screen. If your branding is a corner watermark, put it in the outro art itself.
  8. Using unlicensed music. A track that is fine in a private edit can trigger a claim once uploaded. Use audio you hold the rights to publish.

Troubleshooting

The table covers the problems that come up most often. Start with the symptom you see, then apply the fix on the same row.

SymptomLikely causeFix
The End screen option is missing or greyed out in StudioVideo shorter than 25 seconds, set as made for kids, or a 360 videoCheck length and audience setting, re-export if needed
Studio offers fewer than four elementsAspect ratio is not 16:9Export in 16:9, since the Help page says other ratios may have a lower limit
No external link option appearsChannel is not in the YouTube Partner ProgramUse video, playlist or subscribe elements instead
End screen never shows in a phone browserMobile web is not supported (iPad excepted)Test in the YouTube app or on desktop
Cannot find a valid font or drawtext failsThe font path in OUTRO_FONT is wrongSet OUTRO_FONT to a real TTF path on your system
No such filter: 'drawtext'FFmpeg was built without libfreetypeInstall a build that lists --enable-libfreetype
Stream specifier ':a' matches no streamsA clip has no audio trackAdd a silent track with anullsrc before joining
Outro stutters after joiningFrame rate mismatchUse assemble.sh, which sets the rate from your main video
Checker says FAIL on moov atomFile was written without fast startRun ffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4
Colors look washed out compared with the sourceColor range or matrix mismatchKeep BT.709 tags and TV range and avoid re-encoding in another tool
Frames drawn in the wrong placeSlot coordinates are offRe-run --guide and compare against the Studio preview
Vertical video looks padded on desktopYouTube adds padding to 9:16 in browsersThis is normal behavior, do not add your own bars

Two of these deserve a longer explanation. The audio stream error is the one you will meet first. FFmpeg’s concat filter needs every input to carry the same stream layout, and a screen recording with no microphone has no audio track at all. Generate a silent one and mux it in:

ffmpeg -i video.mp4 -f lavfi -i anullsrc=r=48000:cl=stereo -shortest \
  -c:v copy -c:a aac with-audio.mp4

The washed-out color problem comes from a mismatch between how the file is tagged and how the pixels were converted. The build script avoids it by drawing in RGB and converting once with the BT.709 matrix. If you pass the result through another encoder, that tool may convert again with different defaults. When in doubt, probe the file and compare the color_space field before and after.

Advanced tips

Once the basic YouTube outro template works, these changes save the most time or add the most polish.

Batch outros for a back catalog. If you have 40 older videos you want to give an end screen, loop the assemble script over a folder. The loop below writes each result to a done folder and keeps the originals.

mkdir -p done
for f in raw/*.mp4; do
  bash assemble.sh "$f" outro.mp4 "done/$(basename "$f")"
  python3 check_outro.py "done/$(basename "$f")" || echo "check failed: $f"
done

Make per-series variants from one layout. Copy layout.json to layout-series-a.json, change the headline and accent color, and point the script at it by editing the one read_text line. The slot coordinates stay identical, so your Studio placement habits carry over.

Overlap the sign-off. Start the outro background audio during the last sentence of your talk. In an editor you do this by placing the outro clip’s audio on a second track and fading it up. With FFmpeg, trim the last few seconds of the main video’s audio and mix them under the outro with amix. It takes more filter work but removes the dead-air feel of a hard cut.

Match the Studio layout to the file. Take a screenshot of Studio’s end screen editor after you place the elements, and compare it with the guide render. Adjust layout.json so the guide matches what you actually placed, then re-render. After two or three videos the two agree and you stop thinking about it.

Plan for 4K. For a 4K channel, double every coordinate in layout.json, change the canvas to 3840×2160 and raise the bitrate. YouTube’s bitrate table puts 4K at 35 to 45 Mbps for standard frame rates. The 16:9 check in check_outro.py already accepts any true 16:9 size.

Keep one source of truth for timing. Write the outro length in one place. The build script reads duration from the layout, and the fade-out position and music fade follow it. If you shorten the outro to 10 seconds, change that one value, then update the number you use in Studio to match.

No-code route: the same outro in an editor

You do not need a terminal to follow this design. Any editor with a timeline can reproduce this YouTube end screen template, and the steps map across one for one.

Create a 1920×1080 project at your recording frame rate. Make a 20-second solid color clip for the background. Add the headline as a text layer from 0.3 seconds. Draw three rectangle outlines with the same coordinates as layout.json and make them appear at 0.8 seconds. Add a 0.5-second fade at each end. Export to MP4 with H.264, 8 Mbps for 1080p at 30 fps, AAC at 48 kHz, and BT.709 color. Then join it to the end of your video on the timeline.

What you get on a free plan depends on the editor. Export limits, watermarks and resolution caps differ by app and change often, so check the vendor’s own pricing page before you commit to a tool, and test one short export before you build a whole template library.

If you want the outro to carry motion rather than a static frame, keep movement away from the slot rectangles. Animated backgrounds are fine. Animated shapes that cross a slot will fight the thumbnail Studio draws there.

Questions creators ask

How long can a YouTube end screen be?

Between 5 and 20 seconds, placed in the last part of the video. YouTube’s Help page says end screens can be added to the last 5 to 20 seconds. A 20-second outro uses the full window.

What is the shortest video that can have an end screen?

25 seconds. Below that, Studio does not offer the end screen option. If your clip is short, make sure the content plus the outro passes that mark before you upload.

How many elements can I add?

Up to four on a standard 16:9 video. Other aspect ratios may have a lower limit, so check what Studio offers if you upload vertical or square footage.

What size should a YouTube end screen template be?

For a 16:9 video, use 1920×1080 for 1080p or 3840×2160 for 4K, matching your main footage. Those are the YouTube end screen dimensions to design for, and YouTube’s resolution page lists both as standard 16:9 sizes.

Can I add an end screen to a video made for kids?

No. The Help page lists videos set as made for kids as ineligible, along with 360 videos, the YouTube Music app, the YouTube Kids app and mobile web (iPad excepted).

Do I need to be in the Partner Program to use end screens?

The Help page restricts only external link elements to Partner Program members. Video, playlist, subscribe and channel promotion elements are listed without that restriction.

How long should a YouTube intro be?

YouTube sets no rule in the pages read for this guide, so it is a judgment call. The kit uses 4 seconds and suggests staying under 6. Check your audience retention graph to see whether viewers leave during your intro.

Why does my end screen not show for some viewers?

Viewers can hide end screens, and mobile web does not show them (iPad excepted). Also check that the elements are set inside the final 20 seconds of the video and that you saved the end screen in the editor.

More from the Vipid blog

Make it with Vipid

Theo Vance

Intros & Templates Editor · Vipid Team

Theo Vance is the Intros & Templates Editor at Vipid, where he covers intro and outro makers, template libraries for CapCut, Canva and the major editors, slideshow and video-card tools, and stream starting screens. He compares makers on what matters before you hit render: watermark, export resolution, length limits, licence and price, and dates every check. He also looks after the Vipid theme archive, the 2011–2016 intros the site was built on.

All articles by Theo Vance ›   How we check tools ›

Keep reading

Star Wars Intro Maker [2026]: 7 Tools, 720p Free Cap
Intro Makers

Star Wars Intro Maker [2026]: 7 Tools, 720p Free Cap

Theo Vance·2 Nov 2026
Best Intro Makers [2026]: 6 Ranked by Watermark, Price
Intro Makers

Best Intro Makers [2026]: 6 Ranked by Watermark, Price

Theo Vance·30 Oct 2026
CapCut Templates vs Canva vs Adobe [2026]: 4 Licence Layers
Video Templates

CapCut Templates vs Canva vs Adobe [2026]: 4 Licence Layers

Theo Vance·2 Nov 2026

Blog

Intros & Templates
Titles & Motion
Streaming
Editing & Export
AI Video

Vipid

About Vipid
Themes
News archive 2011–2016
Vipid Team

Editorial

Editorial policy
How we check tools
Corrections

Legal

Privacy policy
Terms of service
Making video intros since 2010.
The Vipid blog covers the tools behind them.