python script for convert video to image sequence using FFmpeg - python

I have 100 uncompressed mov (Video files) and i want to convert all mov to sgi image sequences.
i have a list of all mov file path.
how to convert .mov (video) to .sgi (image sequence) using python and FFmpeg.

you can use ffmpeg to convert the video to sgi images using this ffmpeg command
ffmpeg -i inputVideo outputFrames_%04d.sgi
-replace inputVideo your input file path and name
-replace outputFrames with output file path and name
-replace '4' in _%04d with the number of digits you want for sequential image file naming.
now one way to process your files from python is to launch ffmpeg as a subprocess and providing the command you want executed by ffmpeg:
import subprocess as sp
cmd='ffmpeg -i inputVideo outputFrames_%04d.sgi'
sp.call(cmd,shell=True)
remember to use double \ in your file path in the cmd command string (at least for me on windows).
If you want to loop over 100 movie files, write a loop that concatenates the command string with the appropriate input and output file names.

Related

Write .3gp file into .wav format python Flask server

I need to record a .3gp audio file coming from the Android front-end to be converted into .wav audio using the python Flask server back-end for further processing. Any suggested method or library to convert .3gp audio into .wav audio format?
audiofile = flask.request.files['file']
filename = werkzeug.utils.secure_filename(audiofile.filename)
audiofile.save('Audio/' + filename)
I'm using this code now which receives the audio file as .3gp. I need to convert this into .wav format
Update: You can also do it using ffmpeg
Method 1:
https://github.com/adaptlearning/adapt_authoring/wiki/Installing-FFmpeg#installing-ffmpeg-in-ubuntu
bash
ffmpeg -i path/to/3gp.3gp path/to/wav.wav
or
python (which runs bash command)
import os
os.system('ffmpeg -i path/to/3gp.3gp path/to/wav.wav')
Method 2:
Convert .3gp to .mp3 then .mp3 to .wav
Use https://pypi.org/project/ftransc/ to convert .3gp to .mp3. Currently there is no python API for that so either use
bash
ftransc -f mp3 filename.3gp give the destination - check for help
OR
python
os.system('ftransc -f mp3 filename.3gp')
Then use pydub https://github.com/jiaaro/pydub#installation to convert .mp3 to .wav
newAudio = AudioSegment.from_mp3('path/to/mp3')
newAudio.export('path/to/destination.wav', format="wav")

How do I integrate the FFMPEG commands with Python Script?

I am trying to extract the frames when the scene changes in an .mp4 video.
The package that I am using is FFMPEG.
FFMPEG predominantly works on the CLI and I am trying to integrate it with Python3.x
The command I am using in the CLI is:
ffmpeg -i {0} -vf "select=gt(scene\,0.5), scale=640:360" -vsync vfr frame%d.png
The output comes out just fine with the CLI execution.
But I want to use same command in a Python script, how do I do that and what should be the code?
Being an amateur in the field, currently grappling with this!
You could execute that command from Python via subprocess module, of course, but it would better to use library like https://github.com/kkroening/ffmpeg-python
I would recommend PyAV. it's a proper wrapper around ffmpeg's libraries.
the other mentioned packages use the "subprocess" approach, which is limited and inefficient. these libraries may be more convenient than plain ffmpeg APIs.
Thanks for the help!
This is the snippet of code I'm currently using and it gives the results as I require.
I have added a functionality for timestamp generation of the frames in addition to the frame formation using scene change detection
===========================================================================
> # FFMPEG Package call through script
> # need to change the location in the cmd post -vsync vfr to the location where the frames are to be stored
> # the location should be same as where the videos are located
============================================================================
inputf = []
for filename in os.listdir(path):
file= filename.split('.')[0] # Splits the file at the extension and stores it without .mp4 extension
input_file = path + filename
inputf.append(input_file) # Creates a list of all the files read
for x in range (0, len(inputf)):
cmd = f'ffmpeg -i {inputf[x]} -filter_complex "select=gt(scene\,0.2), scale=640:360, metadata=print:file=time_{file}.txt" -vsync vfr {path where the videos are located}\\{file}_frame%d.jpg'
os.system(cmd)
x=x+1
print("Done") # Takes time will loop over all the videos

Manipulating image output from shell in python without storing external file

I am trying to store an image that is the result of ffmpeg.
Using this command, I have frame.png as an external file output:
ffmpeg -flags2 +export_mvs -i video.avi -vf 'select=gte(n\,200),codecview=mv=pf+bf+bb' -vframes 1 frame.png
I want to be able to load the frame.png directly into python, maybe using openCV but without saving it in the computer.
I thought of something like this:
cmd = "ffmpeg -flags2 +export_mvs -i video.avi -vf 'select=gte(n\,200),codecview=mv=pf+bf+bb' -vframes 1 frame.png"
img = cv.imread(sp.Popen(cmd, shell=True, stdout = sp.PIPE, stderr = sp.PIPE).communicate()[0])
But I get an error:
TypeError: bad argument type for built-in operation
Any clue how to do this? The idea is, no frame.png should be generated as a file.
You can set the output file as /dev/stdout (you might need to specify the output format with -f)
Then you redirect your output to your python script like so
ffmpeg options /dev/stdout | python your_script.py
Then you can read this question to see how you can read an image from a file object. Just replace StringIO with sys.stdin

FFMPEG detect color bars and tone in video

I am trying to detect if a video has any valid content or is just the standard broadcasting bars & tone. So far I've looked at this question: https://superuser.com/questions/1036449/detect-color-bars-ffmpeg/1036478#1036478
which generates bars & tone from the first frame and then compares that against the rest of the stream but in my case I need to run the ffmpeg command within a folder that only has one file that has already been found by my python script.
Is it possible to use ffmpeg's blend=difference to check that a short bars & tone clip is a subclip of one of my video files? I'm thinking of this in the same way you can check if a string is within a string, or is there a better way to check for bars that I'm not thinking of?
Thanks!
I found a way to get my script to do what I wanted with python and ffmpeg:
Info on how this ffmpeg command works:
https://unix.stackexchange.com/questions/101558/compare-video-and-image-percentage-of-differences
http://ffmpeg.org/ffmpeg-filters.html#Video-Filters
-------------------------------------------------------- BEGIN CODE -------------------------------------------------------
selection = "'gt(scene\,0.1)'" # The decimal here is the threshold for determining video quality (0 -> 1)
proc5 = Popen('C:/ffmpeg/bin/ffmpeg.exe -i "'+ src +'" -vf "select='+ selection +'" -vsync 0 -f image2 -y //fn101cdmzst01.foxneo.com/signiant/foxsports/soundmouse/FileManagerInfo/Thumbnails/thumbnails-%02d.jpg 2>&1', stdout=PIPE, shell=True) # This is the ffmpeg command. The specifics of how it works are explained below
res, err = proc5.communicate() # Read proc5's (the ffmpeg command) stdout to res and stderr to err
proc5.wait() # Wait for ffmpeg to finish processing the whole video file
res = str(res.decode('ascii')) # Decode the ascii output from stdout and convert to a string
print(res)
if r"Output file is empty" in res: # If the ascii output from stdout has the string "Output file is empty", remove it. Otherwise, perform name changes and file move for soundmouse
----------------------------------------------------------- END CODE -------------------------------------------------------
FFMPEG COMMAND: 'C:/ffmpeg/bin/ffmpeg.exe -i "'+ src +'" -vf "select='+ selection +'" -vsync 0 -f image2 -y //fn101cdmzst01.foxneo.com/signiant/foxsports/soundmouse/FileManagerInfo/Thumbnails/thumbnails-%02d.jpg 2>&1'
The actual ffmpeg command is highlighted according to the various operations it performs.
C:/ffmpeg/bin/ffmpeg.exe # make an absolute path call to ffmpeg.exe
-i "'+ src +'" # set the absolute path to the source file as the input
-vf "select='+ selection +'" # use a video filter to select frames with large change before and after (based on the decimal threshold that is set) and compare it with the following portion of the command
-vsync 0 -f image2 -y //fn101cdmzst01.foxneo.com/signiant/foxsports/soundmouse/FileManagerInfo/Thumbnails/thumbnails-%02d.jpg # compare the selected frame with the previous one stored in the Thumbnails folder and then overwrite the comparison thumbnail with the selected frame for the next comparison
2>&1' # redirect stderr to stdout so that we can read it with Python's proc5.communicate() function

How to merge two videos?

I use https://github.com/Zulko/moviepy library for merge two videos with python. It merged successfully but sound of videos is not exists in merged.mp4.
The python code :
clip1 = VideoFileClip("2.mp4",audio=True)
clip2 = VideoFileClip("1.mp4",audio=True)
final_clip = concatenate_videoclips([clip1,clip2],method="compose")
final_clip.write_videofile("merged.mp4")
I also tried with ffmpeg
ffmpeg -i 'concat:1.mp4|2.mp4' -codec copy merged.mp4
ffmpeg couldn't merge videos. It create merged.mp4 which has only 1.mp4
How can I merge two videos with python or another way?
ffmpeg offcial
Instructions
Create a file mylist.txt with all the files you want to have concatenated in the following form (lines starting with a # are ignored):
file 'path/to/file1.wav'
file 'path/to/file2.wav'
file 'path/to/file3.wav'
Note that these can be either relative or absolute paths. Then you can stream copy or re-encode your files:
ffmpeg -f concat -safe 0 -i mylist.txt -c copy mergedfile.mp4
The -safe 0 above is not required if the paths are relative.
It works for all kinds of video formats mp4, wav ...

Categories