Text and Graphics Overlay on Video

Difficulty Level = 2 [What’s this?]

The Video Experimenter shield makes it easy to overlay text and graphics onto any composite video signal. Any source of composite video should work — video camera, VCR, DVD player, DVR, cable box, etc.

Text and graphics overlayed onto a TV signal.


Video Experimenter projects require an enhanced version of the TVout library which can be downloaded here. All of the usual TVout drawing primitives can be used to add text or graphics to the screen. Here’s a video of a demo where I had the output of a VCR connected to the Video Experimenter input, then the Video Experimenter output connected to my TV.

The OverlayDemo sketch is in the TVout examples folder.

Here’s the OverlayDemo sketch source code. If you use a television with the PAL standard (that is, you are not in North America), change tv.begin(NTSC, W, H) to tv.begin(PAL, W, H).

#include <TVout.h>
#include <fontALL.h>

#define W 136
#define H 96

TVout tv;
unsigned char x,y;
unsigned char originx = 5;
unsigned char originy = 80;
unsigned char plotx = originx;
unsigned char ploty = 40;
char s[32];
int index = 0;
int messageLen = 32;
char saveChar;
byte ledState = LOW;

void setup()  {
  tv.begin(NTSC, W, H);

// Initialize ATMega registers for video overlay capability.
// Must be called after tv.begin().
void initOverlay() {
  TCCR1A = 0;
  // Enable timer1.  ICES0 is set to 0 for falling edge detection on input capture pin.
  TCCR1B = _BV(CS10);

  // Enable input capture interrupt
  TIMSK1 |= _BV(ICIE1);

  // Enable external interrupt INT0 on pin 2 with falling edge.
  EIMSK = _BV(INT0);
  EICRA = _BV(ISC01);

// Required to reset the scan line when the vertical sync occurs
ISR(INT0_vect) {
  display.scanLine = 0;

void loop() {
  saveChar = message[index+22];
  message[index+22] = '\0';

  for(int x=6;x>=0;x--) {
    if (x<6) {
    tv.print(x, 87, message+index);

    for(byte y=87;y<96;y++) {
      tv.draw_line(0, y, 5, y, 0);
      tv.draw_line(128, y, 134, y, 0);


  message[index+22] = saveChar;
  if (index > 45) {
    index = 0;

  sprintf(s, "%ums", millis());
  tv.print(0, 0, s);

  if (plotx++ > 120) {
    plotx = originx + 1;
  byte newploty = ploty + random(0, 7) - 3;
  newploty = constrain(newploty, 15, originy);
  tv.draw_line(plotx-1, ploty, plotx, newploty, 1);
  ploty = newploty;

void drawGraph() {
  tv.draw_line(originx, 15, originx, originy, 1);
  tv.draw_line(originx, originy, 120, originy, 1);
  for(byte y=originy;y>15;y -= 4) {
    tv.set_pixel(originx-1, y, 1);
    tv.set_pixel(originx-2, y, 1);
  for(byte x=originx;x<120;x += 4) {
    tv.set_pixel(x, originy+1, 1);
    tv.set_pixel(x, originy+2, 1);

Published by Michael, on March 20th, 2011 at 12:45 pm. Filed under: Arduino,Level 2,Video. | 64 Comments |

64 Responses to “Text and Graphics Overlay on Video”

  1. Hi there,

    Nice work going on there. I was wondering if you could overlay sensor values from the arduino to the video?


    Comment by Jan on March 10, 2012 at 3:56 PM

  2. Yes, absolutely. That’s a perfect application.

    Comment by Michael on March 10, 2012 at 4:35 PM

  3. how about a drop shadow or black outline around the white?

    Comment by Anonymous on April 26, 2012 at 12:11 AM

  4. not possible to generate black.

    Comment by Michael on April 26, 2012 at 7:23 AM

  5. Shame about the black – That is a massive limitation , Is it really not possible to make the text easier to read somehow?

    would there be a hardware way of maybe cropping the video so that it ‘ends’ before the text does (i.e leaving a black ‘stripe’ at the bottom of the screen that the overlay text can write to but the video input cannot?

    Comment by Mark on May 16, 2012 at 10:26 AM

  6. You can make a gray or black bar behind the text using some external components. See this :

    Comment by Michael on May 16, 2012 at 10:35 AM

  7. Hello,

    I bought your shield recently works perfectly for my video overlay purpose. currently I’m using my old rear view display (it has composite video input), what I need to use this type of displays with your kit?



    Comment by Tuncay Demirtepe on June 17, 2012 at 8:08 PM

  8. Sorry, this shield only works with composite video. That TFT display on ebay doesn’t seem to have composite input.

    Comment by Michael on June 18, 2012 at 9:24 AM

  9. Got the shield up and running, but I am not sure what the code is doing. Can you help me with a simpler code with just a graph in the middle of the screen. I think that would help a lot! Thanks!

    Comment by John on June 27, 2012 at 4:28 PM

  10. I think you should study the code so you understand it — that way you’ll learn. Delete the parts that deal with the scrolling message. Change the code and see the effect. This is how you’ll learn to use the TV out library.

    Comment by Michael on June 28, 2012 at 7:36 AM

  11. Hello all right?

    Look I’m undertaking a project with this shield only intended to send a message by the Serial Monitor can print and on TV. Whenever you type in the Serial Monitor changed the array of message and logo printed on my TV.

    I made a code that have an array that will be our opening the message I sent a Serial Monitor something and it modifies the array of our message and prints the Serial Monitor.

    So far so good.

    But now when I at the two codes, the code to print the message on TV and Monitor Serial Code, I have tried to solve the problem but still not got along well with the solution is that when I do Serial.begin (9600); setup and also declare the function initOverlay (); I can not get to have the answer in the Serial Monitor with the message I sent. But if I make a comment initOverlay function (), the code works well

    The code that are designed to send the message to the serial monitor and have a conflict with the the initOverlay function () Warning I have not programmed to send me to print to TV. Because I wanted to test whether they could both codes had no conflict and that me from printing the first serial monitor

    Who can help thanked staff and thank you

    Comment by Pedro on June 28, 2012 at 12:21 PM

  12. Pedro, you can’t use Serial with the TVout library. Instead use the pollserial implementation that comes with TVout. See the TVout examples for how to use pollserial.

    Comment by Michael on June 28, 2012 at 2:17 PM

  13. Thank you Michael for helping me thank you But to be able to answer a question The tvout library using the Tx and Rx ports? To make the library functions tvout right?

    Comment by Pedro on June 29, 2012 at 7:56 AM

  14. Yes, the pollserial library uses the TX/RX pins. See the TVout documentation at Google Code.

    Comment by Michael on July 1, 2012 at 4:09 PM

  15. Hello..! guys…!!
    I tried to verify and I get this errors…!!

    VideoFrameCapture.cpp: In function ‘void setup()’:
    VideoFrameCapture:15: error: ‘font4x6’ was not declared in this scope
    VideoFrameCapture.cpp: In function ‘void loop()’:
    VideoFrameCapture:49: error: ‘class TVout’ has no member named ‘capture’
    VideoFrameCapture:51: error: ‘class TVout’ has no member named ‘resume’

    Comment by nao on July 27, 2012 at 2:56 AM

  16. Did you install the library correctly? http://nootropicdesign.com/ve/#library

    Comment by Michael on July 27, 2012 at 5:18 AM

  17. I have a simple question… I am considering using this to take a wireless analog video transmission (receiver uses composite video), strip out the sync signal from that, and have the arduino produce the sync, the idea is to prevent a display from blue screening on a display (requires stable sync signal) when the sync signal from the wireless is lost or screwed up, would this work?

    Comment by Matt on August 4, 2012 at 3:35 AM

  18. Interesting idea, but I’m not sure how you would “strip out” the sync pulses from the video signal. You can detect them, but they are still going to be in the signal. I think what you are saying is that you want to generate a sync pulse along with the existing one, and keep generating it with the same timing even if the sync disappears from the signal? That would be a bunch of software work if you are up to it. It might be possible.

    Comment by Michael on August 4, 2012 at 10:40 AM

  19. I’m have an issue with duplicate overlay images. One overlay looks like it is in the right spot and then it looks like the next frame is just a few inches below it. I’m using the OverlayDemo sketch above and all R4 does is bring it into alignment but does not remove the duplicates. The camera that the image is being overlayed onto is 494×768. Using my cable box the overlay worked without issue so I’ve tried different HxW values.

    Comment by Allen on October 5, 2012 at 9:25 AM

  20. Figured it out. Someone had an additional 75Ohm termination in the line. Once that was removed everything stabilized.

    Comment by Allen on October 6, 2012 at 7:14 AM


    Comment by JULJAN on October 9, 2012 at 9:40 AM

  22. Juljan, why are you SCREAMING?

    It is not easy to make a darker background, but see this thread for some hints on how you can use a MOSFET to do it:

    Comment by Michael on October 9, 2012 at 9:47 AM

  23. why the black color wont work tv.draw_line(0,85,30,85,BLACK); ????

    Comment by JULJAN on October 9, 2012 at 10:06 AM

  24. Juljan, the video overlay can only add voltage to the signal to make it brighter, it cannot remove the signal to give black.

    Comment by Michael on October 9, 2012 at 10:13 AM

  25. Hallo
    This is my firs time that I enter this section.
    I bought a video Experimenter, an arduino UNO USB Microcontroller Rev 3, an E6A2-CS3E encoder(5-12V), and
    a triple axis accelerometer model SEN-09269.
    I have a video signal calming from a camera that I want to overlay on this video signal the distance from the incoder,
    by centimeter and meters , and to see the degree of my movement..
    -1 -2 -3 0 +1 +2 +3.
    On the control box I use a regular analog monitor
    How do I connect all the parts togeder ? And is ther need a programming ? How do I do that
    Best regards
    Levent Rafi

    Comment by Levent rafi on October 16, 2012 at 12:31 AM

  26. Levent, it sounds like you want someone to do your whole project for you…!

    Comment by Michael on October 16, 2012 at 7:11 AM

  27. Hi, really nice project!

    Is it possible to squeeze the overlay part of the screen to a smaller part which in the end increases the resolution? I would like to overlay just the left quarter of the TV screen (helpful in my robot project) use the same amount of memory and increase the resolution accordingly. Could you point me to the piece of code I have to fiddle with?

    Another possibility to increase the resolution could be to organize the screen in separate areas with its own screen memory, so that if most parts of the screen are empty no memory is wasted, ad the gained memory is used to increase the resolution in these areas. Any thoughts on that?


    Comment by Joe on October 30, 2012 at 6:25 PM

  28. Joe,
    You are correct, that you could use less memory if overlaying on only part of the screen. However, there is also a constraint on the timing that makes it impossible to make the pixels any smaller. The speed of a composite signal scanning across the screen is so fast, that we cannot make the pixels any narrower. It takes 6 instruction cycles on the Arduino to perform the work of drawing a pixel, and in that amount of time the scanline covers the width of a low-res pixel. Make sense?

    It is possible to make the pixels smaller vertically. They are currently 2 lines high, but they can be one line high. This doesn’t really help much with resolution because then your pixels are just non-square.

    Frankly, it’s a miracle that any video output at all can be generated by the Arduino. TVout is written in assembly and can’t be optimized any further.

    Comment by Michael on October 30, 2012 at 6:38 PM

  29. Hi Michael,
    thanks for your quick answer!
    I was thinking of another way to create the video output on the MISO pin, I havent done that yet, still in a couple of forums one might get the impression that by using the SPI hardware 320 pixel per line seems to be feasable ( http://www.mikrocontroller.net/topic/53141#413260, unfortunately in German, or http://www.serasidis.gr/circuits/AVR_VGA/avr_vga.htm). This approach is simple in principle, but evil ….
    Trick is to organize the screen in a bitarray per line which is then sent out via SPI, while the underlying TVout library is drawing each pixel one by one.
    As I a said, I dont have hands-on experience on this, but (ab)using SPI seems to be a smart trick. Next issue was to save memory in order to display that higher resolution, which could be done with the selective area trick mentioned preveously
    What do you think?
    Cheers Joe

    Comment by Joe on October 31, 2012 at 6:17 PM

  30. Hi Michael,
    my last reply got lost in the forum somehow, did you get a chance to have a look at it?

    Comment by Joe on November 5, 2012 at 1:48 PM

  31. Can this shield work along with a wifi/ethernet shield? I would like to experiment by showing some text from internet on the video.


    Comment by Bert on January 2, 2013 at 4:27 PM

  32. I have not personally tried it, but it is designed to work with the Ethernet shield. I avoided pin conflicts so that it would work. I just never got around to trying.

    Comment by Michael on January 2, 2013 at 7:24 PM

  33. Thanks for the quick response Michael. Great that you have designed it with much forethought, much appreciate it.

    Comment by Bert on January 2, 2013 at 8:27 PM

  34. Hi Michael,
    I tried using your card on top of ethernet shield. Once the following line is executed in initOverlay() method execution stops

    // Enable input capture interrupt
    TIMSK1 |= _BV(ICIE1);

    Can you suggest some remedy?

    BTW, both ethernet and video card work well independently with arduino uno. Just unable to make it work together.


    Comment by Bert on January 3, 2013 at 6:29 PM

  35. Then it’s probably not going to work. Doing video on the Arduino means using almost all of the CPU and firing interrupts in very quick succession. The Ethernet Shield probably depends on interrupt driven SPI communication, and that typically isn’t going to work well from a timing perspective.

    Comment by Michael on January 3, 2013 at 8:24 PM

  36. Thanks Michael. I am now trying to put video shield on one arduino and ethernet shield on another. I couldnt get hardware serial to work between the two arduino on pins 0 and 1. Wondering if i can use software serial on some other pins. How can I see what pins are being used in your shield? I downloaded your design zip file, but unable to figure out this information.

    Comment by Bert on January 5, 2013 at 1:24 PM

  37. You can’t use ANY interrupt driven peripherals of the Arduino while doing video. You can use the polling version of serial communication that comes with TVout. Use normal hardware pins 0 and 1 for your communication, but use pollserial on the Arduino with the Video Experimenter. See pollserial examples with TVout.

    Comment by Michael on January 5, 2013 at 2:11 PM

  38. Hello, thank you for great project! I really appreciate it! Unfortunately I have problem with contrast of displayed Overlay. The text and chart is very transparent and can be seen only at non-black background. I connected my Video Experimenter between my old-school TV game (NES) and Funai LCD TV. Any Idea what could it be ? How to increase the contrast of overlay? Greetings

    Comment by Andrew on January 28, 2013 at 4:07 PM

  39. I forgot to add that I have Arduino Uno, but it shouldn’t make any difference.

    Comment by Andrew on January 28, 2013 at 4:15 PM

  40. Andrew, have you tried different TVs? The voltage level for the white pixels is 1V, so that should be pure white on the TV. There’s a bit of transparency, but not that much. Try some different equipment, maybe.

    Comment by Michael on January 28, 2013 at 8:12 PM

  41. Thank you for post #28 above – that explains a lot. Could resolution be improved somewhat by halving the pixel height (using one row instead of two), and then effectively changing the characters from a 4×6 to a 4×12? In some characters, this could improve the appearance significantly. How do you change the pixel size from two to one row? Cheers

    Comment by Bill on April 2, 2013 at 5:00 PM

  42. Bill, yes you can halve the pixel height but there’s not enough memory to double the resolution.

    Comment by Michael on April 3, 2013 at 12:48 PM

  43. Hi, I would like to know if this application would be technically feasible using this.

    1. I’d like to capture video from a camera,
    2. process it using the experimenter by encoding more data aside from the video,
    3. transmit feed from experimenter to a video transmitter
    4. capture the feed using a video reciever on a remote location
    5. decode data embedded in step two
    6. display the video in the reciever’s end
    7. display decoded data on a computer.

    I figure i’ll need two shields for encoding and decoding. Knowing the limitations of the videxprmenter, is this possible? Thanks! …

    Comment by johnphilipsolano on April 21, 2013 at 3:37 AM

  44. No, that project is far too ambitious for the Video Experimenter. The Video Experimenter + Arduino cannot record video. It can capture monochrome, low-resolution frames at a very low frame rate (about 3 frames per second). It cannot store them. An Arduino is not nearly powerful enough for your project.

    Comment by Michael on April 21, 2013 at 7:02 AM

  45. Hi,

    This is a really nice product; many thanks!

    I have a couple of quick questiona:

    When I’ve got the switch set to Sync Only, and I get crisp white-on-black. When it’s set to Overlay, I can still see the overlay on the video, but it’s really faint. Any idea why that might be?

    Also, I understand that I have to use pollserial instead of the usual serial API, but what are my chances of getting an I2C device going as well as the Video Experimenter?

    Many thanks,

    Comment by Alec Waters on May 23, 2013 at 4:20 PM

  46. For technical questions please see the forum. Here is an thread about light overlay. By adding a resistor you may be able to fix it.

    I2C is not going to work well while generating a video signal.

    Comment by Michael on May 23, 2013 at 7:49 PM

  47. These command files became known as the Gerber files.
    They also sustain enough space between the elements to allow
    warm dissipation. A PCB is a think board in which electrical
    components are connected using copper tracks instead of wires.

    Comment by Martha on October 2, 2014 at 9:11 PM

  48. Hey, currently trying to use your video experimenter to overlay sensor data on a composite video from a VITEK camera.
    Using a Seeeduino Mega with the jumper wires attached as explained, and the video out is directed to a kworld DVD Maker 2 for computer capture.
    However, running this example code, with or without video input (adjusting d9/vinput and synconly/overlay accordingly) the captured video appears to be all over the place. I assume this means that vertical/horizontal sync is off or something similar, however do not where to begin with this.
    I should note that directly inputting the camera output to the DVD Maker 2 gives a working video feed, it is only through the video experimenter that it does not work.
    Cheers in advance

    Comment by Jay on April 27, 2016 at 11:50 PM

  49. Jay, question moved to support forum: https://nootropicdesign.com/store/forums/topic/video-from-vitek-camera/

    Comment by Michael on April 28, 2016 at 9:50 AM

  50. Hey,
    I just tried to run my Shield with the Code from You for a first System – Check, but somehow my Compiler does not know what the
    – Library is. I installed the TVout Library, and as i included it, many more libraries where shown up, but the fontAll was not there. Do i have to download this library as well or may i need an Update of my Software?

    Thanks in advance

    Comment by Andrew on January 22, 2017 at 8:26 AM

  51. You need to install all 3 libraries: TVout, TVoutfonts, and pollserial. You must use the libraries for the Video Experimenter, not TVout from the internet.

    Follow the instructions here: http://nootropicdesign.com/ve/index.html#library

    Comment by Michael on January 22, 2017 at 10:33 AM

  52. Hello,
    After downloading the latest Version of Arduino, the Libraries where there, now it runs (Y)

    Thank you very much!

    Comment by Andrew on January 25, 2017 at 7:23 AM

  53. Hi there, my goal is to use Arduino TVout library to overlay text and image on another video to make an on screen display. Just wondering, does this shield works with Arduino Leonardo? thank you,
    sincerely, Nikolas

    Comment by Nikolas on February 6, 2017 at 9:40 PM

  54. Sorry, I just read that it would not be working with Arduino Leonardo. But is there any mod I can do to make it work? I really want this shield…

    Comment by Nikolas on February 6, 2017 at 11:52 PM

  55. No, it can’t work on a Leonardo.

    Comment by Michael on February 7, 2017 at 7:57 AM

  56. How about on Arduino mini pro, it uses the same mcu with uno. Is the pinout different?

    Comment by Nikolas on February 7, 2017 at 11:06 AM

  57. Yes, the shield will work with any board based on the ATmega328. Of course it won’t FIT on the pro mini, but you can wire it somehow.

    Comment by Michael on February 8, 2017 at 8:01 PM

  58. Hey there, I finally manage to make the shield work with an Arduino Uno!, just one problem, the text seems to be quite dim… Do you know how to make it brighter? turning the long shaft potentiometer doesn’t seems to help

    Comment by Nikolas on February 11, 2017 at 8:18 PM

  59. Nikolas,
    You should look in the support forum for help, not in the comments here. Anyway, some video sources provide a signal that has a voltage too high and the VE signal gets washed out. It can be fixed with a 330 ohm resistor in parallel with the one on the board. See this discussion in the forum: https://nootropicdesign.com/store/forums/topic/very-light-video-overlay/

    Comment by Michael on February 12, 2017 at 3:27 PM

  60. I am thinking of using this in a high altitude balloon to overlay temperature data onto a video signal from a camera which is being streamed to the ground throug an amateur television transmitter.

    Comment by thomas on May 3, 2017 at 11:57 PM

  61. Hello! Would it be possible to use this video shield to overlay an array of 16-bit-color pixels that were generated by the Arduino (not an Uno) onto the video feed? Memory and processing power shouldn’t be an issue.

    Comment by Zandman 1 on October 18, 2017 at 7:43 PM

  62. No, this product cannot generate any color signal. Only crude monochrome.

    Comment by Michael on October 18, 2017 at 8:06 PM

  63. I am seeing a double image with a faint mirror of the text appearing just to the right of the text. I’m assuming this is due to a dirty input video. Is there any way to filter this out?

    Comment by Eric on January 8, 2018 at 2:14 PM

  64. Hi,

    Video Experimenter shield support for HDTVI technology CCTV camera?
    Can I Connect the Video Experimenter shield in between CCTV camera and DVR and write text above the Vedio?
    HDTVI Technology CCTV Camera (1080P) 2MB and HD Vedio Output camera?

    Comment by T.Uthayathasan on May 8, 2018 at 7:28 AM

Leave a Reply