Search code examples
pythonffmpegcx-freezeffmpy

ffmpeg executable not found when compiled with cx_freeze


I built an executable from a ffmpy code, which I compiled with cx_freeze. It works on my PC, as expected, I think it's because I have ffmpeg installed on my Windows.

However, I need this compiled code to work on any PC, not only where ffmpeg is installed.

When I run the executable, the ffmpy error says, Executable "ffmpeg" not found.

Here is my setup.py for cx_freeze. This setup.py works for anything I want to compile, except where ffmpeg is used.

import sys
from cx_Freeze import setup, Executable
from cx_Freeze import setup
from distutils.core import Extension
import os   

os.environ['TCL_LIBRARY'] = r'C:\Users\Acer\Miniconda3\envs\updated\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Users\Acer\Miniconda3\envs\updated\tcl\tk8.6'


addtional_mods = ['numpy.core._methods', 'numpy.lib.format']
setup(
      name = 'programm',
      version = '5.0.1',
      description = 'PyQt',
      options = {'build_exe': {'includes': addtional_mods}},
      executables = [Executable('ffmpy_test.py', base = "Win32GUI")])

My question is, how can my ffmpy_test.py executable find the ffmpeg.exe in the compiled directory. I tried to place the ffmpeg directory in there, but that didn't work.

This is the test code I compiled:

from ffmpy import FFmpeg

ff = FFmpeg(inputs={'input.wmv': None}, outputs={'output.mp4': None})
ff.cmd
'ffmpeg -i input.ts output.mp4'
ff.run() 

Solution

  • This import statement: from ffmpy import FFmpeg in my python code imports FFmpeg class from the ffmpy module.This class looks for ffmpeg.exe on C:/ffmpeg/bin/ffmpeg.exe, where ffmpeg is installed on my Windows.

    Inspired by @l'L'l's comment, I looked into how ffmpeg is imported inside the FFmpeg class in the ffmpy module.

    In the ffmpy module:

    class FFmpeg(object):
        """Wrapper for various `FFmpeg <https://www.ffmpeg.org/>`_ related applications (ffmpeg,
        ffprobe).
        """
    
        def __init__(self, executable='ffmpeg', global_options=None, inputs=None, outputs=None):
            ...
    

    So, I needed to change the path in the executable argument in order to direct the import statement to the ffmpeg directory which I placed manually inside the directory where my code is located.

    But, I modified the default value of the executable argument in my code, not in the ffmpy module, like so:

    from ffmpy import FFmpeg
    import os
    d = os.getcwd()
    ff = FFmpeg(executable=d+'/ffmpeg/bin/ffmpeg.exe',inputs={'input.wmv': None}, outputs={'output.mp4': None})
    ff.cmd
    'ffmpeg -i input.wmv output.mp4'
    ff.run()