I am trying to loop over a directory of sub folders where every folder contains one .avi file that i want to retrieve its length in seconds.
I've found PyMedia http://pymedia.org/ and i understand it could possibly help me achieve this but i cannot find anything about avi duration / length in the documentation.
How would i be able to do that? also, if there is a different library of some sort i'd like to know aswel.
Edit: Added my final solution that works thanks to J.F. Sebastian
import sys
import glob
import os
from hachoir_core.cmd_line import unicodeFilename
from hachoir_core.i18n import getTerminalCharset
from hachoir_metadata import extractMetadata
from hachoir_parser import createParser
path = "z:\*"
for fpath in glob.glob(os.path.join(path, '*avi')):
filename = fpath
filename, real_filename = unicodeFilename(filename), filename
parser = createParser(filename, real_filename=real_filename)
metadata = extractMetadata(parser)
print fpath
print("Duration (hh:mm:ss.f): %s" % metadata.get('duration'))
print '\n'
You could use hachoir-metadata to extract avi duration from a file:
#!/usr/bin/env python
import sys
# $ pip install hachoir-{core,parser,metadata}
from hachoir_core.cmd_line import unicodeFilename
from hachoir_core.i18n import getTerminalCharset
from hachoir_metadata import extractMetadata
from hachoir_parser import createParser
filename = sys.argv[1]
charset = getTerminalCharset()
filename, real_filename = unicodeFilename(filename, charset), filename
parser = createParser(filename, real_filename=real_filename)
metadata = extractMetadata(parser)
print("Duration (hh:mm:ss.f): %s" % metadata.get('duration'))
It uses pure Python RIFF parser to extract info from avi file.
Example:
$ get-avi-duration.py test.avi
Duration (hh:mm:ss.f): 0:47:03.360000
Here's ffmpeg's output for comparison:
$ ffmpeg -i test.avi |& grep -i duration
Duration: 00:47:03.36, start: 0.000000, bitrate: 1038 kb/s
To print info about all avi files in a directory tree:
#!/usr/bin/env python
import os
import sys
from hachoir_metadata import extractMetadata
from hachoir_parser import createParser
def getinfo(rootdir, extensions=(".avi", ".mp4")):
if not isinstance(rootdir, unicode):
rootdir = rootdir.decode(sys.getfilesystemencoding())
for dirpath, dirs, files in os.walk(rootdir):
dirs.sort() # traverse directories in sorted order
files.sort()
for filename in files:
if filename.endswith(extensions):
path = os.path.join(dirpath, filename)
yield path, extractMetadata(createParser(path))
for path, metadata in getinfo(u"z:\\"):
if metadata.has('duration'):
print(path)
print(" Duration (hh:mm:ss.f): %s" % metadata.get('duration'))
If your server running any UNIX operation system you can use ffmpeg to do this. Usually just default command like ffmpeg myvideo.avi will give you full video details.
There's also a python wrapper for ffmpeg which probably will return video details in dictionary or list.
EDIT:
I've also found nice ffmpeg tool called ffprobe which can output length of video without additional fuss.
fprobe -loglevel error -show_streams inputFile.avi | grep duration | cut -f2 -d=
Not sure if there is a platform independent way to do this, but if you only need this to work on windows then it looks like MediaInfo (below) has a command line interface which you can use to output details about video files, which could then be parsed to get the information. Not the prettiest solution but looks like it should work.
http://mediainfo.sourceforge.net/en
Related
I would like to package a folder into a file, I do not need compression. All alternatives I tried were slow.
I have tried:
The zipfile library with ZIP_STORED (no compression)
import zipfile
output_filename="folder.zip"
source_dir = "folder"
with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_STORED) as zipf:
zipdir(source_dir, zipf)
The tarfile library also using w to open the file for writing
without compression
import tarfile
import os
output_filename="folder.tar"
source_dir = "folder"
with tarfile.open(output_filename, "w") as tar:
tar.add(source_dir, arcname=os.path.basename(source_dir))
But both still take ~3-5 minutes to package a folder that is ~5GB and has < 10 files in it.
I am using a Linux machine.
Is there a faster way?
I am not quite sure if it is that faster but if you are running linux you could try tar command:
import time
import os
start = time.time()
os.system("tar -cvf name.tar /path/to/directory")
end = time.time()
print("Elapsed time: %s"%(end - start,))
If you also need file compression you need to add gzip after the first command:
os.system("gzip name.tar")
For instance, i have five .mp4 in a folder. How do i loop and convert them to .mp3 and output them in a different folder?
Thanks
I have tried this but it is not working.
**import moviepy.editor as mp
import re
tgt_folder = "D:/Music/video"
for file in [n for n in os.listdir(tgt_folder) if re.search('mp4',n)]:
full_path = os.path.join(tgt_folder, file)
output_path = os.path.join(tgt_folder, os.path.splitext(file)[0] + '.mp3')
clip = mp.AudioFileClip(full_path).subclip(10,) # disable if do not want any clipping
clip.write_audiofile('D:/Music/mp3')**
you can do this by using ffmpeg and python subprocces
import subprocess
subprocess.run(["ffmpeg", "-i video.mp4 -b:a 192K -vn music.mp3"])
hello I have many pdf files and I eant to convert to .eps using python.
I have find some codes but don't work for me that codes execute without some error but I don't take some .eps file .
any idea ?
I have python 2.7.13
code 1 :
from glob import *
from os import system
fileList = glob('*.pdf')
for f in fileList:
system('pdftops -eps {0}'.format(f))
code 2 :
import os, re, sys
dirList = os.listdir( '.' )
try:
os.mkdir( 'EpsFigs' )
except:
pass
for f in dirList:
m = re.match('([\w\-]+).(|jpg|jp2|png|pdf|)$',f)
if m:
cmd = 'convert %s EpsFigs/%s.eps'%( f, m.group(1) )
os.system(cmd)
Use linux command pdf2ps to convert pdf to eps.
pdf2ps [ options ] input.pdf [output.ps]
For example,
pdf2ps input.pdf output.eps
If you really want to use python, you can call the above command with subprocess.call:
from subprocess import call
call(["pdf2ps", "input.pdf", "output.eps"])
Reference
pdf2ps
subprocess
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)
Re-organizing a large MP3 library for my friend's MP3 Player, I have the need to name the Title ID3 tag the same as the file name, and doing this via Windows Properties takes forever, so I was wondering if anyone has an idea of how to make a Python script that does this to all MP3's in a directory in rapid succession. Or at least a link to a library installable on Windows.
Look at this:
ID3 Tagging in Python
id3reader
Also Dive Into Python uses MP3 ID3 tags as an example.
Don't forget about PyPI - the Python Package Index.
Here is a python script I wrote to do this https://gitlab.com/tomleo/id3_folder_rename
#! /usr/bin/python
import os
import re
import glob
import subprocess
from mutagen.easyid3 import EasyID3
path = os.getcwd()
fpath = u"%s/*.mp3" % path
files = glob.glob(fpath)
for fname in files:
_track = EasyID3(fname)
track_num = _track.get('tracknumber')[0]
track_title = re.sub(r'/', '_', _track.get('title')[0])
if '/' in track_num:
track_num = track_num.split('/')[0]
if len(track_num) == 1:
track_num = "0%s" % track_num
_valid_fname = u"%s/%s %s.mp3" % (path, track_num, track_title)
if fname != _valid_fname:
subprocess.call(["/bin/mv", fname, _valid_fname])
It uses the mutagen python library for parsing the ID3 info. You'll have to tweak the subprocess call it to make it work with windows, but this should give you an idea for how to do it. Hope this helps.