ffmpeg convert image sequence to video - python

image sequences start with
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1001
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1002
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1003
using
ffmpeg -i D:/imagesequence/sdhdfd_plate/sdhdfd_plate_bg01_v001_fds_fdse_fdfd.%04d.jpg -vf "[in]drawtext=fontsize=32:fontcolor=White:fontfile='/Windows/Fonts/arial.ttf':text='shotName':x=(w)/2:y=(h)-50[out]" D:/Uss/Temp/sdhdfd_plate_bg01_v001_fds_fdse_fdfd.%04d.jpg
following error occurs
D:/imagesequence/sdhdfd_plate/sdhdfd_plate_bg01_v001_fds_fdse_fdfd.%04d.jpg: N
o such file or directory
is it possible to convert these type images using ffmpeg

There seems to be a couple reasons why this isn't working. First, as pointed out by pixelistik, if your images don't actually have .jpg extensions, it won't work (eg, if they're actually png or something).
Secondly, your image sequence has to start at 0 or 1, so starting at 1001 won't work. You can use this batch code or something like it in a UNIX shell to rename your images into a workable sequence.
x=1; for i in *jpg; do counter=$(printf %04d $x); ln "$i" sdhdfd_plate_bg01_v001_fds_fdse_fdfd."$counter".jpg; x=$(($x+1)); done
Note that you must be in the directory holding the images, and if there are other images that you don't want included, you'll have to change for i in *jpg to something like for i in sdhdfd_plate_bg01_v001_fds_fdse_fdfd.*.

seems pattern does not work under windows.
your pattern is incorrect,
for files:
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1001.jpg
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1002.jpg
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1003.jpg
the input pattern should be:
sdhdfd_plate_bg01_v001_fds_fdse_fdfd.1%03d.jpg
here the 1%03d mapping to: 1001, 1002, 1003...

Related

Count the audio tracks in a movie file with python

I'm trying to get the number of audio tracks in a video file. The video have multiple tracks (like different, selectable languages for the same movie.) So if there are three optional languages for the video, i'd like to get the number 3 in the end, no matter if the audio is in stereo, mono or in 5.1.
So far I tried to do it with moviepy. I found only the function "reader.nchannels", but that counts only the first audio track's left and right channel, so I get the number 2 every time.
The code right now is really simple, it looks like this:
from moviepy.editor import *
from moviepy.audio import *
clip = VideoFileClip(source)
audio_tracks = clip.audio.reader.nchannels
I also tried to get every info from the audio like this:
audio = AudioFileClip(source)
tracks= audio_tracks.reader.infos
The output for this looks like this:
"'audio_found': True, 'audio_fps': 48000}"
tburrows13, thanks for pointing to the right direction.
I was able to get the numbers of audio channels and store it in a variable through a py script. Maybe this is not the most elegant solution, but it works, so here it is, if someone needs it. You have to import "subprocess" and use ffprobe with it. ffprobe comes with ffmpeg.
To get the number of streams the command goes like this:
ffprobe <filename here> -show_entries format=nb_streams
This will give you the number of streams in the file, not just the audios, but the video streams too. There is an option to get the data only for the audio streams, but this was not necessary for my project.
You can call this command through a python script. The command needs to be a string, you can store it in a variable too. To get and store the output of this commmand in an other variable you can use this:
variable = subprocess.check_output(subprocesscommand) # subprocesscommand is the string version of the command wrote above.
If you print out now this variable the output will be something like: b'[FORMAT]\r\nnb_streams=3\r\n[/FORMAT]\r\n'
Now you just need to slice the string value, to get the number of the streams.
Thanks again for your help!

Using ffmpeg with Python3 subprocess to convert multiple PNGs to a video

I am using Python3, subprocess and ffmpeg to convert multiple PNG images into a single video.
I have 400 PNG numbered as "00001.png".
This call for one single specific image to a a one-frame-video works:
subprocess.call(["ffmpeg","-y","-r","24","-i", "00300.png","-vcodec","mpeg4", "-qscale","5", "-r", "24", "video.mp4"])
However, when I try some methods seen online for calling all of my images formated as "#####.png" using "%05d.png" as below, it does not work anymore:
subprocess.call(["ffmpeg","-y","-r","24","-i", "%05d.png","-vcodec","mpeg4", "-qscale","5", "-r", "24", "video.mp4"])
I receive the error : "%05d.png: No such file or directory".
I have the feelling that the above syntax is proper to Python2 and not working on my python3 but can't find the correct python3 syntax anywhere.
Thanks in advance for your help
Well, I finally found the answer, and as expected it is disappointingly simple: The numbering has to start with 1 (00001 in my case), while in fact my files ranged from 00002.png to 00301.png.
Worked as soon as I added an initial 00001.png file.

making a GIF from imges in any order with python

I'm trying to make a gif out of a sequence of png format pics with python language in ubuntu 12.04. I have a file which my pictures are in it. they are named as, lip_shapes1.png to lip_shapes11.png. also I have a list with names of images in it which i want to make that gif in this sequence. the list looks like this:
list = [lip_shapes1.png, lip_shapes4.png , lip_shapes11.png, lip_shapes3.png]
but my problem is that i found this code :
import os
os.system('convert -loop 0 lip_shapes*.gnp anime.gif')
but it only makes gif in the order of the gnp's names, but I want it to be in any order I want. is it possible?
if anybody can help me i really appreciate it.
thanks in advance
PS: i also want to make a movie out of it. i tried this code(shapes is my list of images names):
s = Popen(['ffmpeg', '-f', 'image2', '-r', '24', '-i'] + shapes + ['-vcodec', 'mpeg4', '-y', 'movie.mp4'])
s.communicate()
but it gives me this in terminal and doesnt work:
The ffmpeg program is only provided for script compatibility and will be removed
in a future release. It has been deprecated in the Libav project to allow for
incompatible command line syntax improvements in its replacement called avconv
(see Changelog for details). Please use avconv instead.
Input #0, image2, from 'shz8.jpeg':
Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
Stream #0.0: Video: mjpeg, yuvj420p, 266x212 [PAR 1:1 DAR 133:106], 24 tbr, 24 tbn, 24 tbc
shz8.jpeg is the first name on the list.
thanks
If you use subprocess.call, you can pass the filenames as a list of strings. This will avoid shell quotation issues that might arise if the filenames, for example, contained quotes or spaces.
import subprocess
shapes = ['lip_shapes1.png', 'lip_shapes4.png' , 'lip_shapes11.png', 'lip_shapes3.png']
cmd = ['convert', '-loop0'] + shapes + ['anime.gif']
retcode = subprocess.call(cmd)
if not retval == 0:
raise ValueError('Error {} executing command: {}'.format(retcode, cmd))
So you've got a list of images you want to convert into gif as a python list. You can sort it or arrange in any order you want. e.g
img_list = ['lip_shapes1.png', 'lip_shapes4.png' , 'lip_shapes11.png', 'lip_shapes3.png']
img_list.sort()
Please note that list should not be used as variable name, because it's a name of list type.
Then you can use this list in calling os.system(convert ...) e.g.
os.system('convert -loop 0 %s anime.gif' % ' '.join(img_list))
You should be sure to handle a few things here, if you want to read a series of pngs from a folder, I recommend using a for loop to check for the ending of the file, i.e. .png, .jpg, etc. I wrote a blog post on how to easily do this (read about it here):
image_file_names = [],[]
for file_name in os.listdir(png_dir):
if file_name.endswith('.png'):
image_file_names.append(file_name)
sorted_files = sorted(image_file_names, key=lambda y: int(y.split('_')[1]))
This will put all the '.png' files into one vector of file names. From there, you can loop through the files to customize the gif using the following:
images = []
frame_length = 0.5 # seconds between frames
end_pause = 4 # seconds to stay on last frame
# loop through files, join them to image array, and write to GIF called 'test.gif'
for ii in range(0,len(sorted_files)):
file_path = os.path.join(png_dir, sorted_files[ii])
if ii==len(sorted_files)-1:
for jj in range(0,int(end_pause/frame_length)):
images.append(imageio.imread(file_path))
else:
images.append(imageio.imread(file_path))
# the duration is the time spent on each image (1/duration is frame rate)
imageio.mimsave('test.gif', images,'GIF',duration=frame_length)
here's an example produced by the method above:
https://engineersportal.com/blog/2018/7/27/how-to-make-a-gif-using-python-an-application-with-the-united-states-wind-turbine-database

Generate PDF from JPEGs in Separate Directories Grouped by Date/Name

I am looking to generate a PDF report from JPEGs on a server. The JPEGs are in folders named after the location they were taken and the JPEGs are named based on the date they were taken (...\Location 1\15 08 03 description.jpg). Basically I need to grab all pictures taken at each site last month, group them evenly on a page (4 max/page), label the pages with location and date, export PDF.
I have written projects in Powershell and Python so it would be a lot easier for me to operate in these languages but I will consider all suggestions.
So far, my idea is to use switch/case to select the various folder names, for loop through to select all cases, and select all files with .jpg extension within a month range (maybe user prompted?). Where I fall flat is arranging the JPEGs into a PDF as I described.
Edit: So if you follow Mark Setchell's advice below, create the images he suggested and place them in C:\New folder. So suppose you had in this sub directory 3 folders (New folder, New folder (2), etc.) and 2 of these contain the nine colored JPEGS and the third is empty:
clear
$path="C:\New folder\"
$array=#()
$name="file*.jpg"
foreach ($i in Get-ChildItem -path $path -Filter "New*")
{$i0=$path+$i; Get-ChildItem -path $i0 -Filter $name | ForEach-Object {$array+= $i0+"\"+$_.name}
montage $array -tile 2x2 -geometry +5+5 -title $i -page letter montage.pdf}`
My code overwrites the title on all pages with that of the 3rd empty folder. Also, it begins adding JPEGS from the next folder into the previous page, which should be titled as the previous folder and only contain those JPEGS.
Imagine you have 9 JPEG files in a directory, called file1.jpg...file9.jpg and they were created like this as lumps of red, green, blue, cyan, magenta, yellow, black and gray.
convert -size 300x400 xc:red file1.jpg
convert -size 300x400 xc:lime file2.jpg
convert -size 300x400 xc:blue file3.jpg
convert -size 300x400 xc:cyan file4.jpg
convert -size 300x400 xc:magenta file5.jpg
convert -size 300x400 xc:yellow file6.jpg
convert -size 300x400 xc:black file7.jpg
convert -size 300x400 xc:gray40 file8.jpg
convert -size 300x400 xc:gray80 file9.jpg
If you now go into that directory and run the following bash script, it will montage the files into pages of A4 with 4 images on each page.
#!/bin/bash
for f in file*jpg; do
convert -label "$f" "$f" -depth 8 miff:-
done | montage -tile 2x2 -geometry +5+5 miff:- -page A4 montage.pdf
The crux of the matter is firstly adding a label to each image based on the filename and secondly sending the label and the image to a MIFF file which is capable of holding many images. The combined group of images are then fed into montage whch arranges them four to a page because of the -tile 2x2. The geometry sets the spacing between the pictures - bigger numbers mean bigger spaces. Finally we tell montage that the paper size is A4 and we want a PDF of all the input images - please!
Of course you can diddle with the background, the sizing, the spacing and the labelling till you are happy - but this should give you the basic idea.
You will get out a PDF called montage.pdf with these three pages:
Page1
Page 2
Page 3
Its shoud be fairly trivial to convert the loop to an ugly Windows-y FOR loop - for loop help.
for converting your jpg's into pdf files you can use ImageMagick.
There are also different types of python APIs for imagemagick, but in your case is the best to write a simple powershell script and execute imagemagick directly.
Just use the following imagemagick command:
convert <yourfile.jpg> <newfile.pdf>
Note: You must use file extentions in your command. Otherwise imagemagick don't know what todo.
You could use glob to get the files (and then sort them if needed). I think the switch could get way too complicated.
As for the convert part: Shibumi's answer.

Saving thumbnails as fits files

Most of my code takes a .fits file and creates small thumbnail images that are based upon certain parameters (they're images of galaxies, and all this is extraneous information . . .)
Anyways, I managed to figure out a way to save the images as a .pdf, but I don't know how to save them as .fits files instead. The solution needs to be something within the "for" loop, so that it can just save the files en masse, because there are way too many thumbnails to iterate through one by one.
The last two lines are the most relevant ones.
for i in range(0,len(ra_new)):
ra_new2=cat['ra'][z&lmass&ra&dec][i]
dec_new2=cat['dec'][z&lmass&ra&dec][i]
target_pixel_x = ((ra_new2-ra_ref)/(pixel_size_x))+reference_pixel_x
target_pixel_y = ((dec_new2-dec_ref)/(pixel_size_y))+reference_pixel_y
value=img[target_pixel_x,target_pixel_y]>0
ra_new3=cat['ra'][z&lmass&ra&dec&value][i]
dec_new_3=cat['dec'][z&lmass&ra&dec&value][i]
new_target_pixel_x = ((ra_new3-ra_ref)/(pixel_size_x))+reference_pixel_x
new_target_pixel_y = ((dec_new3-dec_ref)/(pixel_size_y))+reference_pixel_y
fig = plt.figure(figsize=(5.,5.))
plt.imshow(img[new_target_pixel_x-200:new_target_pixel_x+200, new_target_pixel_y-200:new_target_pixel_y+200], vmin=-0.01, vmax=0.1, cmap='Greys')
fig.savefig(image+"PHOTO"+str(i)+'.pdf')
Any ideas SO?
For converting FITS images to thumbnails, I recommend using the mJPEG tool from the "Montage" software package, available here: http://montage.ipac.caltech.edu/docs/mJPEG.html
For example, to convert a directory of FITS images to JPEG files, and then resize them to thumbnails, I would use a shell script like this:
#!/bin/bash
for FILE in `ls /path/to/images/*.fits`; do
mJPEG -gray $FILE 5% 90% log -out $FILE.jpg
convert $FILE.jpg -resize 64x64 $FILE.thumbnail.jpg
done
You can, of course, call these commands from Python instead of a shell script.
As noted in a comment, the astropy package (if not yet installed) will be useful:
http://astropy.readthedocs.org. You can import the required module at the beginning.
from astropy.io import fits
At the last line, you can save a thumbnail FITS file.
thumb = img[new_target_pixel_x-200:new_target_pixel_x+200,
new_target_pixel_y-200:new_target_pixel_y+200]
fits.writeto(image+str(i).zfill(3)+'.fits',thumb)

Categories

Resources