Hi everyone! My last devlog was about how the multi scene stitching works. This one is about a bug that stopped Codecast from working for anyone but me, which took a while to track down because the app worked totally fine on my own computer the whole time.
The problem
Someone downloaded the Codecast .exe, opened it, hit export, and no video file came out at all. No video, no message, nothing. On my computer the exact same .exe made a video every single time, so at first I had no idea what was different on their end.
What I thought it was at first
Codecast uses a tool called ffmpeg to actually build the video out of the frames and the narration, so my first guess was that they just hadn’t installed ffmpeg. That seemed like the obvious answer. So I had them install it, but it still didn’t work. I even tried it on a second computer that had ffmpeg installed and set up correctly, and it broke there too. So the issue wasn’t a missing install, it was a real bug in my app.
How I actually found it
The annoying part is that I built the .exe with a --windowed flag, which hides the console, so when it crashed there was nothing to see, it just quietly did nothing. So I rebuilt it without --windowed so the black console window would stay open and show me whatever went wrong. That’s when the actual error finally showed up: a FileNotFoundError when the app tried to run ffprobe which gets data like duration, file size, etc. . Ffprobe is a part of ffmpeg which stitches the frames and audio into a video.
The strange thing is that ffmpeg was installed and it was on the system PATH, so the computer should have been able to find it. After messing around with it I figured out that it only broke when running as the .exe, never when I ran the plain python ui.py version. It turns out PyInstaller bundles don’t go looking for the system PATH in the same way a normal program does, so even with ffmpeg sitting right there on the computer, the bundled .exe couldn’t find it.
How I solved it
Instead of relying on the user’s computer having ffmpeg somewhere it could find, I bundled ffmpeg and ffprobe directly inside the .exe so it carries its own copy and never has to go searching the system at all.
The tricky bit is that the code has to find these tools whether it’s running as plain Python code or as the packed .exe, and the bin folder location is different for these two scenarios. When PyInstaller runs the .exe, it extracts all the bundled files and puts it into a temporary folder and stores that folder’s location in sys._MEIPASS. So I made a little helper method that checks for that:
def resource_path(filename):
if hasattr(sys, "_MEIPASS"):
base = sys._MEIPASS
else:
base = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base, "bin", filename)
So if sys._MEIPASS exists, the application is running as the .exe and I look in the temp folder, and if it doesn’t, then it’s running as normal code and I just look next to my script. Either way it finds the bin folder where the two necessary tools live.
Then I built the exe with this:
pyinstaller --onefile --windowed --add-data "bin;bin" ui.py
The --add-data "bin;bin" part is what tells PyInstaller to pack thebin folder into the .exe too.
How I tested it
To really make sure it was standalone, I uninstalled ffmpeg off another laptop entirely, so there was no ffmpeg anywhere on the system, and then ran the .exe file. It still made the video therefore that means the user doesn’t need to install ffmpeg themselves to use the application
Why this matters
The reason this matters is mainly convenience. Before this update, the user would have to go onto my Github repository, install ffmpeg themselves and then use my application which could be a time consuming task. Now you just need to install the .exe file and run it.