How to cut videos automatically using Python with FFmpeg? - python

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

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! :)

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

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)

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)

Search large tar.gz file for keywords,copy and delete

What is the best way with large log tar.gz files , some are 20 gig , to open and search for a keyword, copy found files to a directory , then delete the file so it doesn't consume disk space.
I have some code below, it was working but then it stopped extracting files suddenly for some reason. If i remove the -O option from tar it extracts files again.
mkdir -p found;
tar tf "$1" | while read -r FILE
do
if tar xf "$1" "$FILE" -O | grep -l "$2" ;then
echo "found pattern in : $FILE";
cp $FILE found/$(basename $FILE);
rm -f $FILE;
fi
done
$1 is the tar.gz file , $2 is the keyword
UPDATE
Im doing the below which works, but a small file i have has 2million plus compressed files, so will take hours to look at all the files.Is there a python solution or similar that can do it faster.
#!/bin/sh
# tarmatch.sh
if grep -l "$1" ; then
echo "Found keyword in ${TAR_FILENAME}";
tar -zxvf "$2" "${TAR_FILENAME}"
else
echo "Not found in ${TAR_FILENAME}";
fi
true
tar -zxf 20130619.tar.gz --to-command "./tarmatch.sh '#gmail' 20130619.tar.gz "
UPDATE 2
Im using python now and seems to of increased in speed, was doing about 4000 records a second while the bash version was doing about 5.Im not that strong in python so probably this code could be optimized, please let me know if this could be optimized.
import tarfile
import time
import os
import ntpath, sys
if len(sys.argv) < 3 :
print "Please provide the tar.gz file and keyword to search on"
print "USAGE: tarfind.py example.tar.gz keyword"
sys.exit()
t = tarfile.open(sys.argv[1], 'r:gz')
cnt = 0;
foundCnt = 0;
now = time.time()
directory = 'found/'
if not os.path.exists(directory):
os.makedirs(directory)
for tar_info in t:
cnt+=1;
if (tar_info.isdir()): continue
if(cnt%1000 == 0): print "Processed " + str(cnt) + " files"
f=t.extractfile(tar_info)
if sys.argv[2] in f.read():
foundCnt +=1
newFile = open(directory + ntpath.basename(tar_info.name), 'w');
f.seek(0,0)
newFile.write( f.read() )
newFile.close()
print "found in file " + tar_info.name
future = time.time()
timeTaken = future-now
print "Found " + str(foundCnt) + " records"
print "Time taken " + str( int( timeTaken/60) ) + " mins " + str(int(timeTaken%60)) + " seconds"
print str( int(cnt / timeTaken)) + " records per second"
t.close()
If you are trying to search for a keyword in the files and extract only those, and since your file sizes are huge, it might take time if the keyword is somewhere at the middle.
The best advice I can give is probably use a powerful combination of a Inverted index lookup tool such as Solr(based on Lucene Indes) and Apache Tika - a content analysis toolkit.
Using these tools you can index the tar.gz files and when you search for a keyword, relevant documents containig the keyword will be returned.
If the file is really 20GB it will take very long to grep in any case. The only advice I can give is to use zgrep. This will save you from having to explicitly uncompress the archive.
zgrep PATTERN your.tgz

Categories

Resources