ffmpeg, Video HTML streaming

FFmpeg – watermarks

If you want to create watermarks for video using ffmpeg, this might be useful. Here is an example.

We have our input video file source.mp4 and image file image.png. We want to create output file output.mp4 with watermark using the image file.

ffmpeg -y -i source.mp4 -i image.png -filter_complex "[1]format=bgra,colorchannelmixer=aa=1,rotate=0:c=black@0:ow=rotw(0):oh=roth(0)[image];[0][image]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" output.mp4

The number in [] represents number of input (0,1,…). We have here only two inputs: [0] and [1]. First we are setting up image:

  • opacity – aa=1 means that the image is not transparent (value can be 0 – 1)
  • rotation – rotate=0, rotw(0), roth(0) means that the image is not rotated (instead of “0” we can add any value in radians)

Secondly we are overlaying input [0] (source.mp4) with [image] (our rotated and transparent image).

Now we have our video with watermarks. But what if we need to add more watermarks to one video. Here is an example of adding 3 different watermarks to video (image1.png, image2.png and image3.png):

ffmpeg -y -i source.mp4 -i image1.png -i image2.png -i image3.png -filter_complex "[1]format=bgra,colorchannelmixer=aa=1,rotate=0:c=black@0:ow=rotw(0):oh=roth(0)[image1];[2]format=bgra,colorchannelmixer=aa=0.8,rotate=1.5:c=black@0:ow=rotw(1.5):oh=roth(1.5)[image2];[3]format=bgra,colorchannelmixer=aa=0.5,rotate=-2:c=black@0:ow=rotw(-2):oh=roth(-2)[image3];[0][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay1];[overlay1][imag2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay2];[overlay2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" output.mp4

First, we are setting up three different images:

  • [image1] – input [1], opacity = 1, rotation = 0
  • [image2] – input [2], opacity = 0.8, rotation 1.5 rad
  • [image3] – input [3], opacity = 0.5, rotation -2 (minus means opposite direction)

Secondly:

  • overlaying input [0] (our source.mp4) with [image1] and creating [overlay1]
  • overlaying [overlay1] with [image2] and creating [overlay2]
  • overlaying [overlay2] with [image3] and creating output.mp4 with all watermarks

I have written generation of arguments for ffmpeg in C# for adding watermarks:

private static string CreateArgs(string input, List<Watermark> watermarkInputs)
      {
         var buffer = new StringBuilder();
         var buffer2 = new StringBuilder();
         buffer.Append("-y ");
         buffer.AppendFormat("-i \"{0}\" ", input);
 
         foreach (var watermarkInput in watermarkInputs)
            buffer.AppendFormat("-i \"{0}\" ", watermarkInput.Path);
 
         if (watermarkInputs.Any())
            buffer.Append("-filter_complex \"");
 
         var previousOverlay = "0";
         var last = watermarkInputs.LastOrDefault();
         foreach (var watermarkInput in watermarkInputs)
         {
            buffer.AppendFormat("[{0}]format=bgra,colorchannelmixer=aa={1},rotate={2}:c=black@0:ow=rotw({2}):oh=roth({2})[{3}];",
               watermarkInput.Order,
               watermarkInput.Opacity.HasValue ? watermarkInput.Opacity.Value : 1,
               watermarkInput.Rotation / -57.2958, //to radians and oposite direction
               watermarkInput.Id);
            buffer2.AppendFormat("[{0}][{1}]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2", previousOverlay, watermarkInput.Id);
            if (!last.Equals(watermarkInput))
            {
               var newOverlay = Guid.NewGuid().ToString();
               buffer2.AppendFormat("[{0}];", newOverlay);
               previousOverlay = newOverlay;
            }
         }
 
         if (watermarkInputs.Any())
         {
            buffer.Append(buffer2.ToString());
            buffer.Append("\" ");
         }
 
         buffer.AppendFormat("output.mp4");
 
         return buffer.ToString();
      }

You will need this class for using this method:

public class Watermark
   {
      public int Rotation { get; set; } // in degrees
      public double? Opacity { get; set; } // 0 - 1
      public string Path { get; set; } // path to image file
      public string Id { get; set; } // unique id (Guid)
      public int Order { get; set; } // from 1 -> * (0 is video input)
   }

You can combine this with conversion and encrypting:

ffmpeg -y -i source.mp4 -i image1.png -i image2.png -i image3.png -filter_complex "[1]format=bgra,colorchannelmixer=aa=1,rotate=0:c=black@0:ow=rotw(0):oh=roth(0)[image1];[2]format=bgra,colorchannelmixer=aa=0.8,rotate=1.5:c=black@0:ow=rotw(1.5):oh=roth(1.5)[image2];[3]format=bgra,colorchannelmixer=aa=0.5,rotate=-2:c=black@0:ow=rotw(-2):oh=roth(-2)[image3];[0][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay1];[overlay1][imag2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay2];[overlay2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -hls_time 1 -hls_key_info_file key.info -hls_playlist_type vod -hls_segment_filename "output\fileSequence%d.ts" "output\stream.m3u8"

About converting to HLS and encrypting your video for most browsers, go to HLS – encrypting and playing video (videojs).

1 thought on “FFmpeg – watermarks”

Leave a comment