I am trying to create a video downloader, that can download only from youtube.com and vimeo.com
I can get the script to work fine on my machine, both running from IDE and the pyinstaller .exe, but running the .exe I created on another machine gives a FileNotFoundError.
I am still relatively new to coding, so may be something obvious I am missing, or some knowledge that I need to go and learn about. Any advice towards this is appreciated
I have tried including the ffmpeg.exe and yt-dlp.exe in their own folders, so folder structure is as follows:
main.exe
ffmpeg
ffmpeg.exe
yt-dlp
yt-dlp.exe
I am using main.spec to build the executable with pyinstaller, I have included both main.py and main.spec below
main.py:
import os
import platform
import subprocess
import sys
def get_videos_path():
if platform.system() == 'Windows':
return os.path.join(os.environ['USERPROFILE'], 'Videos')
elif platform.system() == 'Darwin':
return os.path.join(os.environ['HOME'], 'Movies')
else:
raise Exception('Unsupported operating system.')
def sanitize_filename(filename):
return "".join(c for c in filename if c.isalnum() or c in (' ', '.', '_')).rstrip()
def get_ffmpeg_path():
# find the ffmpeg executable.
if getattr(sys, 'frozen', False):
# If the application is run as a bundle
if platform.system() == 'Windows':
return os.path.join(sys._MEIPASS, 'ffmpeg', 'ffmpeg.exe')
else:
return os.path.join(sys._MEIPASS, 'ffmpeg', 'ffmpeg')
else:
# If the application is run as a script
if platform.system() == 'Windows':
return os.path.join(os.path.dirname(__file__), 'ffmpeg', 'ffmpeg.exe')
else:
return 'ffmpeg' # Adjust for other systems if necessary
def download_video(url, output_path):
if not os.path.exists(output_path):
os.makedirs(output_path)
# Construct yt-dlp command
command = [
'yt-dlp',
'--impersonate', 'Safari', # Ensure impersonation target is specified
'--format', 'bestvideo+bestaudio/best', # Format selection
'--merge-output-format', 'mp4', # Merge formats into mp4
'--ffmpeg-location', get_ffmpeg_path(), # Specify FFmpeg location
'--output', os.path.join(output_path, '%(title)s.%(ext)s'), # Output template
url
]
# Ensure FFmpeg is correctly detected
ffmpeg_path = get_ffmpeg_path()
print(f"FFmpeg path: {ffmpeg_path}")
os.environ['PATH'] += os.pathsep + os.path.dirname(ffmpeg_path)
print(f'''Video downloading now, and will be output to {output_path}.
The console will close automatically when the video is downloaded.''')
try:
# Execute the yt-dlp command
subprocess.run(command, check=True)
print(f"Video downloaded and merged successfully to {output_path}")
except subprocess.CalledProcessError as e:
print(f"Error: {e}")
# Actual script, get user input and run the commands
video_url = ""
while 'youtube.com' not in video_url.lower() and "vimeo.com" not in video_url.lower():
video_url = input("Please paste the video url here. Youtube or Vimeo only: ")
output_path = get_videos_path()
download_video(video_url, output_path)
main.spec:
# –– mode: python ; coding: utf-8 ––
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[('ffmpeg', 'ffmpeg')],
hiddenimports=['yt_dlp'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
will beard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.