Several years ago at work we were looking to do some quick and dirty watermarking of spec audio that was produced in-house. It was to be done on workstations that did not have our regular audio production software installed and licensed. At the time it didn’t seem there was much of anything available for software that would do the trick. What we did find was either sketchy looking, or were full suites of audio production software (such as our producers use), or just didn’t quite do what we wanted. We wanted something that some of our non-audio production people could use quickly and easily at their desk. I was just getting into Python at that time, and said I would see what I could do.
In looking for the best way to do it, I came across the Pydub library created by jiaaro. I found it easy to use with the features that I needed. I thought it might be fun in this article to go over a simple audio watermarking example project very similar to what I put in place. Bear in mind, I am not a professional developer, so real developers out there may run screaming at some of what I do. My goal with the article is to hopefully give other people ideas and make them aware of the libraries and tools involved in the project so they can utilize them in their own way. I have tweaked, refined, and built on this idea as I have written more Python and explored more libraries, and I am sure many people out there will have a myriad of ideas that would improve this basic idea.
I did the following scripting on Win XP/7 originally, and have transferred it to Win8.x/10 as well. All the components are available for Linux as well, I just haven’t bothered trying it on a Linux box yet…I believe the only thing different would be the ‘right click context’ feature I used.
What I Used / Conditions
I used the following components and conditions to implement my test script. If you aren’t familiar with ffmpeg and Pydub, I encourage you to do a bit of reading to see what their general capabilities are. You will need to install/create the following items if you don’t already have them on your system :
- Python 2.7x (I used Win32)
- ffmpeg (I used Win32 static)
- Pydub
- Python 2.7x and ffmpeg should be in your environment variable path
- C:\watermarking folder (we will place our test script in this directory)
- C:\watermarked folder (Our final audio output will land in this directory)
- A test mp3 audio file anywhere on your machine (a single song would work, I used a 30 second commercial break for testing)
- A file named (in my case) watermark.mp3 in the C:\watermarking folder to use as our ‘overlay’ watermarking audio
The Script
Enter the following script and save it under a name of your choice. For the purposes of this example article I named mine watermarkbeta.py.
1. from Pydub import AudioSegment
2. import os
3. import time
4. import sys#watermarkbeta.py, or whatever name you want to use
#Python audio watermarking script that takes
#one argument (the name of the audio file being watermarked)
#overlays a second audio file over the beginning and outputs
#it to a destination folder/file
#requires Pydub and ffmpeg libraries/frameworks
5. rawcom = sys.argv[1]
6. print "Now watermarking audio file : ", rawcom
7. time.sleep (3)8. commercial = AudioSegment.from_mp3 (rawcom)
9. watermrk = AudioSegment.from_mp3("C:/watermarking/watermark.mp3")#Lines 10-13, 19 are optional, specific to my implementation
10. intro = watermrk (:2750)
11. mrk = watermrk (2900:)
12. output1 = intro + commercial
13. output2 = output1.overlay (mrk, position = 3200)
#But if you would like to play with splitting audio, try them out14. output1 = commercial.overlay(watermrk, position = 200)15. (outputpath, outputfile) = os.path.split (rawcom)
16. print outputfile
17. dest = os.path.join ('C:/watermarked/','Copr-' + outputfile)
18. output1.export (dest, format = "mp3")#Line 19 is paired with the optiona 10-13 abovfe
19. output2.export (dest, format = "mp3")20. sys.exit()
- Lines 1–4 : Here we are importing the specific Pydub library function that I need, along with some other general imports for the script
- Line 5 : Here, we are passing our first command line argument and assigning it to rawcom. This is the name of the file that you want watermarked. Interesting bit of info — sys.argv[0] is the name of the Python script you are running
- Line 6–7 : Just a bit of information for troubleshooting and for the end-user, letting them see what file is being processed and delaying for three seconds (the value in brackets) using the sleep() function
- Line 8 : We are assigning the value we passed to rawcom earlier to commercial as an AudioSegment object for later use
- Line 9 : We are assigning our watermarking audio file to an AudioSegment object called watermrk for later use
- Line 10–13 : Specific to my situation when I created the script, but I included it for interests sake. I was given a piece of watermark audio that included a verbal copyright notice, followed by a loud, annoying beep. We wanted the verbal notice tacked onto the beginning of the audio file, and the beep following after. If the watermarking audio was supplied in two separate files, I could have appended one to the beginning and overlaid the second. As it was, I used it as an exercise to split the object into intro and mrk objects , add the intro to the commercial and then overlay the mrk on the result. Take a look at the Pydub documentation with regards to AudioSegment and see what properties are available. The brackets taking integer values in line 10–11 are time in milliseconds slicing out pieces of the watermrk object
- Line 14 : Instead of using line 10–13 (feel free play with splitting and cutting if you wish though) you can simply overlay the watermrk file object on the commercial file object, resulting in output1. This takes two parameters, our watermrk object, and an integer that represents milliseconds from the start of the commercial audio object where the watermrk object starts to overlay it
- Line 15–16 : We use the os.path.split function, which takes the information we passed into rawcom and divides it up into everything before the final slash (the path) and everything after (the specific file). Optionally, you can then print the outputfile information for the users benefit
- Line 17 : We create an object called dest and use os.path.join to merge the output path of our watermarked file with the abbreviation ‘copr-’ and the ‘outputfile’ name from line 15
- Line 18 : We now export the whole deal which takes two parameters, the ‘dest’ value from line 17 and the file format, which we have specified as ‘mp3’.
Right Click Context
In my case, I would be implementing my final script on workstations for some of my users. They were not comfortable going to the command line, and I didn’t want them doing so regardless, so I wanted a way for them to run this easily on an audio file anywhere on their computer. I considered a GUI version of the script (and did create one just for fun) but after doing a bit of research, decided that adding a ‘Watermark audio’ option to their Windows right click context menu might be the fastest and most painless option. In order to do this, I made a change to the Windows registry.
Standard disclaimer here — do a backup of your registry before making any modifications to it, and if you have not made registry changes before, do a bit of research to familiarize yourself. I won’t be held responsible for any blood, pain, or heartache resulting from any changes you make:)
Run regedit.exe to open your Windows registry editor and navigate to the following location :
HKEY_CLASSES_ROOT\*\shell\
We want to create a key called Watermark and inside that key, one called command. To do this:
- right-click on the shell entry on the left pane in your registry editor, and choose new. Create a new key called Watermark
- Right-click on your new Watermark key and choose new again to create a key called command Inside the command key we will set the default value to the following :
python.exe "C:\watermarking\watermarkbeta.py" "%1"
The “C:\watermarking\watermarkbeta.py” is the path of the completed script from earlier in the article, change it to what is appropriate for your script if yours is different than my example. The “%1” is a variable that contains the name of the file that you have passed to your script, in this case the audio file we are right-clicking on.
Remember the quotations around the entries in the default value. The script will work fine without them, unless there are spaces in either the path, or the value that is passed to %1. If there are spaces and you have not quoted these in the registry, the values will not be parsed correctly, and your script will not execute.
You can use the above registry edit to add a variety of objects or executables to your right click context.
Putting It Together
In a perfect world where I have made no mistakes in the above guide, you should now be able to right click on your test guinea pig .mp3 file, choose ‘Watermark’ from the list, and watch a command line window appear briefly telling you what it is doing. If successful, in your ‘C:\watermarked\’ folder you should now find a copy of your original file with your watermark audio overlaid on it near the beginning.
Things to Think About
I have used Pydub+ffmpeg for several projects now. Ffmpeg is a tried and true audio framework that is used by countless people, projects and organizations. Though I am not an experienced Python programmer, I have been very happy with both of these projects and find them flexible and easy to use with many options.
The following are a few thoughts on things you could do to expand or improve this idea, along with some things I have already done :
- I created a similar script that converts .wav files to .mp3 files and utilizes the right click context feature…do a bit of research on Pydub and take and give it a try
- Add logging to your script — have it open a log/txt file when it is run and append an entry to it each time. You could include things the date and time and the names and paths of the files involved
- I added Syslog capability to my script as an exercise in learning about syslogging for another system at work. I had my test workstations sending a message to my Syslog server each time the script was run. Check out the Syslog standards and protocols, there is some very cool stuff that can be done with it
- Add some error/exception handling to the script. I have none in this example, but do some reading on basic exception handling, add a try block, and give it a graceful exit in the event that someone tries to pass or watermark a non-audio file
If you can get past my amateur-hour Python skills, I hope this article gave everyone some ideas to pursue in their Python programming, especially as it relates to Pydub, ffmpeg, and audio manipulation.