i use moviepy
for merge mp3 and mp4 file. it's working good but the process is so slow. i use multi threads but the main process(merging) is still slow. i search and know that i use ffmpeg
but i get error at first try and i cant fix it. so i came back to moviepy and is there any way to speed up this process?
my code is so simple: just read the name of my files and get them and merge mp3 file with mute mp4 files. btw i coded with threading
and as i say it have not progress. (Of course, there is a possibility that I don't drink well with Multi-Thread! God knows!)
import threading
from os import walk
from moviepy.editor import VideoFileClip, AudioFileClip
from concurrent.futures import ThreadPoolExecutor
def merge_audio_and_video(name):
print(f"Processing {name}...")
video = VideoFileClip(name + '.mp4')
audio = AudioFileClip(name + '.m4a')
final_video = video.set_audio(audio)
final_video.write_videofile(
f'./merge/{name}.mp4', codec="libx264", audio_codec="aac"
)
filenames = next(walk('.'), (None, None, []))[2]
mp4_files = [file for file in filenames if file.endswith('.mp4')]
mp4_files_without_extension = [file.replace('.mp4', '') for file in mp4_files]
with ThreadPoolExecutor(max_workers=1) as executor:
futures = [executor.submit(merge_audio_and_video, name)
for name in mp4_files_without_extension]
for future in futures:
future.result()
print("All video files have been processed.")
output and it/s show the speed of process for the file 20MB
:
t: 77%|█████████ | 16138/20868 [12:07<02:25, 32.52it/s, now=None]
this is all detail of mp4 file:
{
"abr": 0,
"acodec": "none",
"aspect_ratio": 1.78,
"audio_ext": "none",
"container": "mp4_dash",
"downloader_options": {
"http_chunk_size": 10485760
},
"dynamic_range": "SDR",
"ext": "mp4",
"filesize": 116113997,
"filesize_approx": 116113932,
"format": "298 - 1280x720 (720p60)",
"format_id": "298",
"format_note": "720p60",
"fps": 60,
"has_drm": false,
"height": 720,
"id": "66b3bba14f6a5",
"language_preference": -1,
"protocol": "https",
"quality": 8,
"resolution": "1280x720",
"source_preference": -1,
"tbr": 1215.164,
"vbr": 1215.164,
"vcodec": "avc1.640020",
"video_ext": "mp4",
"width": 1280
}
and this is m4a file detail:
{
"abr": 129.479,
"acodec": "mp4a.40.2",
"asr": 44100,
"audio_channels": 2,
"audio_ext": "m4a",
"container": "m4a_dash",
"downloader_options": {
"http_chunk_size": 10485760
},
"ext": "m4a",
"filesize": 12373283,
"filesize_approx": 12373223,
"format": "140 - audio only (medium)",
"format_id": "140",
"format_note": "medium",
"has_drm": false,
"id": "66b3bba146875",
"language": "en",
"language_preference": -1,
"protocol": "https",
"quality": 3,
"resolution": "audio only",
"source_preference": -1,
"tbr": 129.479,
"vbr": 0,
"vcodec": "none",
"video_ext": "none"
}
i try the acodec
from data that i get but throw error:
final_video.write_videofile(
f'./merge/{name}.mp4', codec='libx264', audio_codec="mp4a.40.2"
)
raise ValueError(
ValueError: The audio_codec you chose is unknown by MoviePy. You should report this. In the meantime, you can specify a temp_audiofile with the right extension in write_videofile.
edit final:
import subprocess
def merge_audio_and_video(name):
print(f"Processing {name}...")
command = [
'ffmpeg', '-i', f'{name}.mp4', '-i', f'{name}.m4a',
'-c:v', 'copy', '-c:a', 'aac', f'./merge/{name}.mp4'
]
subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
so i fix ffmpeg error and i use it. it have good speed. but is there any way to handle this without using ffmpeg??
Use subprocess to run ffmpeg in the shell
. If your task is to add additional audio or video track to the file then ffmpeg
is the best tool to use. It will have least overheads.
import subprocess
input = 'ffmpeg -i video1.mp4 -i audio1.m4a -c copy output.mp4'
quiet = False
stream = subprocess.DEVNULL if quiet else None
subprocess.call(input,
stdout = stream,
stderr = stream,
shell = True)