Merge Audio and Video using ffmpeg - Python Lib [duplicate] - python

I'm trying to combine a video(with no sound) and its separate audio file
I've tried ffmpeg ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4
and it works fine.
i'm trying to achieve the same output from ffmpeg-python but with no luck. Any help on how to do this?

I had the same problem.
Here is the python code after you have pip install ffmpeg-python in your environment:
import ffmpeg
input_video = ffmpeg.input('./test/test_video.webm')
input_audio = ffmpeg.input('./test/test_audio.webm')
ffmpeg.concat(input_video, input_audio, v=1, a=1).output('./processed_folder/finished_video.mp4').run()
v=1:
Set the number of output video streams, that is also the number of video streams in each segment. Default is 1.
a=1: Set the number of output audio streams, that is also the number of audio streams in each segment. Default is 0.
For the details of ffmpeg.concat, check out: https://ffmpeg.org/ffmpeg-filters.html#concat.
You can check out more examples here: https://github.com/kkroening/ffmpeg-python/issues/281
Hope this helps!
PS.
If you are using MacOS and have the error:
FileNotFoundError: [Errno 2] No such file or directory: 'ffmpeg' while running the code, just brew install ffmpeg in your terminal.

You could use subprocess:
import subprocess
subprocess.run("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4")
You can also use fstrings to use variable names as input:
videofile = "video.mp4"
audiofile = "audio.mp4"
outputfile = "output.mp4"
codec = "copy"
subprocess.run(f"ffmpeg -i {videofile} -i {audiofile} -c {codec} {outputfile}")

import ffmpeg
input_video = ffmpeg.input("../resources/video_with_audio.mp4")
added_audio = ffmpeg.input("../resources/dance_beat.ogg").audio.filter('adelay', "1500|1500")
merged_audio = ffmpeg.filter([input_video.audio, added_audio], 'amix')
(ffmpeg
.concat(input_video, merged_audio, v=1, a=1)
.output("mix_delayed_audio.mp4")
.run(overwrite_output=True))
you can review this link https://github.com/kkroening/ffmpeg-python/issues/281#issuecomment-546724993

Added the following code:
https://github.com/russellstrei/combineViaFFMPEG
It walks the directory, finds ".mp4" files, adds it to the file to be used by ffmpeg, then executes the command.
for name in glob.glob(directory +"\\"+ '*.mp4'):
print(name)
file1 = open(processList, "a") # append mode
file1.write("file '" + name + "'\n")
file1.close()
execute()
def execute():
cmd = "ffmpeg -f concat -safe 0 -i " + processList + " -c copy "+ dir + "output.mp4"
os.system(cmd)

Related

how do I fix this ffmpeg code to convert multiple folders to multiple mp4

i have this code and I want to iterate through each folder in this directory, collect the files in each directory, and output it as 1 video per folder.
I keep getting the following error
"Could find no file with path './inputFrames/08KKF_Right/08KKF_Right.%04d.png' and index in the range 0-4
./inputFrames/08KKF_Right/08KKF_Right.%04d.png: No such file or directory
ffmpeg -f image2 -r 30 -i ./inputFrames/08KKF_Right/08KKF_Right.%04d.png -vcodec mpeg4 -y ./videos/08KKF_Right.mp4"
This is my code:
import os
dirs = os.listdir('./inputFrames/')
for x in dirs:
frames = os.listdir('./inputFrames/' + x)
#print(frames)
for y in frames:
yFrameO = y[:-8]
yFrame = "./inputFrames/"+ yFrameO[:-1] + "/"+ yFrameO + "%04d.png"
inputOS = "ffmpeg -f image2 -r 30 -i " + yFrame + " -vcodec mpeg4 -y ./videos/" + yFrameO[:-1]+".mp4"
#print(inputOS)
print("\n")
os.system(inputOS)
This is the code that works for a single folder that I'm trying to make work for multiple folders:
os.system("ffmpeg -f image2 -r 30 -i ./08KKF_Right/08KKF_Right.%04d.png -vcodec mpeg4 -y ./videos/08KKF_Right.mp4")
It tries to run the command on each image in each sub-Folder, so I get over 900 function calls and each of them erroring with the
how do I make it work for each folder? all the videos can be output to a single folder called "./videos"
thank you! :)

Errno2 no such file or directory

i've been trying to run sox in a python script but it can't the output file and gives me [errno2]
def AudioToSpectrogram(self, files, pixel_per_sec, height, width):
file_name = ("tmp_{}.png").format(random.randint(0, 100000))
command = "sox -V0 {} -n remix 1 rate 10k spectrogram -y {} -x {} -X {} -m -r -o {}".format(files, height, width, pixel_per_sex, file_name)
p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
Output, errors = p.communicate()
If errors:
Print(errors)
Image = Image.open(file_name)
Os.remove(file_name)
Return np.array(image)
This is the error it gives
Exception: [errno2] No such file or Directory: 'tmp_47483.png'
I hope you could give me some pointers since i am still new in this field, thanks in advance!
Assuming tmp_47483.png is in fact being created, the problem is likely that the command is placing the file in a different folder and Python can't find it inside the current working directory. The
# manually set the full path (make sure the backslashes are escaped by putting two each)
file_name = f"C:\\Full\\Path\\To\\File\\tmp_{random.randint(0, 100000}.png"
# use the os module to join the path
base_dir = "C:\\Full\\Path\\To\\File"
file_name = os.path.join(base_dir, f"tmp_{random.randint(0, 100000}.png")
# if you want it to appear in the same folder as your script:
CWD = os.path.dirname(os.path.realpath(__file__)) # mostly fool-proof way of getting a script's Current Working Directory
file_name = os.path.join(CWD, f"tmp_{random.randint(0, 100000}.png")
Try these and see if they help. If not, make sure that command is actually working and outputting a file somewhere.

How to cut videos automatically using Python with FFmpeg?

I'm trying to cut videos automatically using Python with FFmpeg so I don't have to type out the command everytime I want a new video cut. I'm not really sure what I'm doing wrong though, here's the code:
import os
path = r'C:/Users/user/Desktop/folder'
for filename in os.listdir(path):
if (filename.endswith(".mp4")):
command = "ffmpeg - i" + filename + "-c copy -map 0 -segment_time 00:00:06 -f segment -reset_timestamps 1 output%03d.mp4"
os.system(command)
else:
continue
Typos
First of all, there's a typo in the syntax, as you wrote - i while the correct syntax is -i.
The syntax " + filename + " is correct, however there must be a space before and after
command = "ffmpeg -i " + filename + " -c copy -map 0 -segment_time 00:00:06 -f segment -reset_timestamps 1 output%03d.mp4"
otherwise, you would get an error like
Unrecognized option 'iC:\Users\user\Desktop\folder\filename.mp4-c'.
Error splitting the argument list: Option not found
Solution
I assumed every other argument is correct, for me it didn't work at first, I just had to add
-fflags +discardcorrupt
but maybe it's just my file.
Here's the correct code, however I recommend to you to read this.
Note: I used os.path.join() to save the output file in that same directory because my python file was in another one.
import os
path = r'C:\Users\user\Desktop\folder'
for filename in os.listdir(path):
if filename.endswith(".mp4"):
command = "ffmpeg -fflags +discardcorrupt -i " + os.path.join(path, filename) + " -c copy -map 0 -segment_time 00:00:03 -f segment -reset_timestamps 1 " + os.path.join(path, "output%03d.mp4")
os.system(command)
else:
continue
You can cut a video file with ffmpeg.
ffmpeg -i 1.mp4 -vcodec copy -acodec copy -ss 00:03:20 -t 00:10:24 out.mpt
-ss : start_time
-to : end_time
-t : duration_time

How to combine The video and audio files in ffmpeg-python

I'm trying to combine a video(with no sound) and its separate audio file
I've tried ffmpeg ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4
and it works fine.
i'm trying to achieve the same output from ffmpeg-python but with no luck. Any help on how to do this?
I had the same problem.
Here is the python code after you have pip install ffmpeg-python in your environment:
import ffmpeg
input_video = ffmpeg.input('./test/test_video.webm')
input_audio = ffmpeg.input('./test/test_audio.webm')
ffmpeg.concat(input_video, input_audio, v=1, a=1).output('./processed_folder/finished_video.mp4').run()
v=1:
Set the number of output video streams, that is also the number of video streams in each segment. Default is 1.
a=1: Set the number of output audio streams, that is also the number of audio streams in each segment. Default is 0.
For the details of ffmpeg.concat, check out: https://ffmpeg.org/ffmpeg-filters.html#concat.
You can check out more examples here: https://github.com/kkroening/ffmpeg-python/issues/281
Hope this helps!
PS.
If you are using MacOS and have the error:
FileNotFoundError: [Errno 2] No such file or directory: 'ffmpeg' while running the code, just brew install ffmpeg in your terminal.
You could use subprocess:
import subprocess
subprocess.run("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4")
You can also use fstrings to use variable names as input:
videofile = "video.mp4"
audiofile = "audio.mp4"
outputfile = "output.mp4"
codec = "copy"
subprocess.run(f"ffmpeg -i {videofile} -i {audiofile} -c {codec} {outputfile}")
import ffmpeg
input_video = ffmpeg.input("../resources/video_with_audio.mp4")
added_audio = ffmpeg.input("../resources/dance_beat.ogg").audio.filter('adelay', "1500|1500")
merged_audio = ffmpeg.filter([input_video.audio, added_audio], 'amix')
(ffmpeg
.concat(input_video, merged_audio, v=1, a=1)
.output("mix_delayed_audio.mp4")
.run(overwrite_output=True))
you can review this link https://github.com/kkroening/ffmpeg-python/issues/281#issuecomment-546724993
Added the following code:
https://github.com/russellstrei/combineViaFFMPEG
It walks the directory, finds ".mp4" files, adds it to the file to be used by ffmpeg, then executes the command.
for name in glob.glob(directory +"\\"+ '*.mp4'):
print(name)
file1 = open(processList, "a") # append mode
file1.write("file '" + name + "'\n")
file1.close()
execute()
def execute():
cmd = "ffmpeg -f concat -safe 0 -i " + processList + " -c copy "+ dir + "output.mp4"
os.system(cmd)

ffmpeg in python script

I would like to run the following command in a python script, I also want to make it loop over several videos in a folder. This is the command I want to run.
ffmpeg -i mymovie.avi -f image2 -vf fps=fps=1 output%d.png
I want to fit it in something like this:
import ffmpy
import os
path = './Videos/MyVideos/'
for filename in os.listdir(path):
name = filename.replace('.avi','')
os.mkdir(os.path.join(path,name))
*ffmpeg command here*
I found a wrapper for ffmpeg called ffmpy, could this be a solution?
From a brief look at FFMPY, you could do this using ffmpy.FFmpeg, as that allows any and all FFMPEG command line options, including -f. -- Click the link for documentation.
You could do the FFMPEG command with os.system. You'll need to import OS anyway to iterate through the files.
You would need to iterate through all the files in a directory though. This would be the more challenging bit, it's quite easy with a for loop though.
for filename in os.listdir(path):
if (filename.endswith(".mp4")): #or .avi, .mpeg, whatever.
os.system("ffmpeg -i {0} -f image2 -vf fps=fps=1 output%d.png".format(filename))
else:
continue
The above code iterates through the directory at path, and uses command prompt to execute your given FFMPEG command, using the filename (if it's a video file) in place of mymovie.avi
Dont have reputation to comment, hence adding another response.
Another version of ocelot's answer with the more readable f-string syntax of python -
for filename in os.listdir(path):
if (filename.endswith(".mp4")): #or .avi, .mpeg, whatever.
os.system(f'ffmpeg -i {filename} -f image2 -vf fps=fps=1 output%d.png')
else:
continue
Try pydemux in https://github.com/Tee0125/pydemux. Pydemux module can extract video frames as in Pillow Image format
from PyDemux import Video
v = Video.open('video.mov')
i = 0
while True:
im = v.get_frame()
if im is None:
break
im.save('output%d.png'%i)
i = i + 1
This is a way to use ffmpeg in a python script, e.g. for extracting the last 10 seconds of every video:
ffmpeg -sseof -10 -i input.mp4 output.mp4
To apply this to a whole folder of mp4 files:
from pathlib import Path
import os
suffix = ".mp4"
input_path= Path.home() / "Desktop/foo"
file_paths= [subp for subp in input_path.rglob('*') if suffix == subp.suffix]
file_paths.sort()
output_path = Path.home() / "Desktop/foo/new"
output_path.mkdir(parents=True, exist_ok=True)
for file_p in file_paths:
input = str(file_p)
output = str( output_path / file_p.name )
command = f"ffmpeg -sseof -10 -i {input} {output}"
print(command)
os.system(command)

Categories

Resources