c0decracker / video-splitter Goto Github PK
View Code? Open in Web Editor NEWSimple Python script to split video into equal length chunks or chunks of equal size, duration, etc.
License: Apache License 2.0
Simple Python script to split video into equal length chunks or chunks of equal size, duration, etc.
License: Apache License 2.0
Hi, is there any option to split all videos in a folder?
Thanks.
I love this script, it finally got me using ffmpeg. My only question, is it possible to apply this to a folder of video files? Thank you!
Hi,
Example: video of 39 minute length. I want to split it into equal sizes. Each size should not exceed 15 minutes.
Traditionally with -s 900 I would get three parts: 15min, 15min, 9min. I want however three parts of equal length which would be 13min. Obviously I could fetch a calculator and type in the seconds I want. Still the script could do this automagically :)
While Splitting video having more than one audio stream, the output videos contain only 1 audio stream.
ffmpeg default stream selection will not automatically choose all of the streams from video
Using the '-map' option disables the default stream selection behavior and allows you to manually choose streams.
Adding -map 0 in command will select all streams from input video
reference: https://trac.ffmpeg.org/wiki/Map
There is small lag when two consecutive splitted videos are played. Can you fix it ?
Thanks for this script! Very well done.
I'm noticing that when I run it, the resulting files begin with a few seconds of white (though the audio is intact). I'm wondering if you came across it all all on your end. Possibly a codec issue?
D:\video\main>python ffmpeg-split.py -f video.mp4 -s 10
Traceback (most recent call last):
File "D:\video\main\ffmpeg-split.py", line 224, in
main()
File "D:\video\main\ffmpeg-split.py", line 220, in main
split_by_seconds(video_length=video_length, **options.dict)
File "D:\video\main\ffmpeg-split.py", line 96, in split_by_seconds
video_length = get_video_length(filename)
File "D:\video\main\ffmpeg-split.py", line 77, in get_video_length
output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of",
File "C:\Python310\lib\subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:\Python310\lib\site-packages\run_init_.py", line 145, in new
process = cls.create_process(command, stdin, cwd=cwd, env=env, shell=shell)
File "C:\Python310\lib\site-packages\run_init_.py", line 121, in create_process
shlex.split(command),
File "C:\Python310\lib\shlex.py", line 315, in split
return list(lex)
File "C:\Python310\lib\shlex.py", line 300, in next
token = self.get_token()
File "C:\Python310\lib\shlex.py", line 109, in get_token
raw = self.read_token()
File "C:\Python310\lib\shlex.py", line 140, in read_token
nextchar = self.instream.read(1)
AttributeError: 'tuple' object has no attribute 'read'
Is there a fix for this?
Hello C0decracker,
thanks for the small python script regarding letting ffmpeg do multiple jobs in order to losslessly splitting sourcefile.
I needed cuesheet support for doing non-equidistantly splits, therefore I added cuesheet-support.
I got no idea about how to operate git and the like, but I think this project is small enough to just give you my work here:
#!/usr/bin/env python
import subprocess
import re
import math
from optparse import OptionParser
length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,'
cue_reffile_regexp = 'FILE\s"(.*)"'
cue_index_regexp = 'INDEX\s01\s(\d{2}):(\d{2}):(\d{2})'
re_length = re.compile(length_regexp)
re_cue_reffile = re.compile(cue_reffile_regexp)
re_cue_index = re.compile(cue_index_regexp)
#splitbin = "ffmpeg"
splitbin = "avconv"
def main():
(filename, split_length) = parse_options()
if split_length <= 0:
# Cuesheet operation (individual split lengths)
cuefile = open (filename)
cue=cuefile.read ()
cuefile.close ()
filename = re_cue_reffile.search(cue).group(1)
#This finds only the first FILE; there should be only one FILE per cuesheet for this script being and working reasonable.
split_points = [int(indx.group(1))*60 + int(indx.group(2)) + float(indx.group(3))/75 for indx in re_cue_index.finditer(cue)]
equal = False
else:
equal = True
output = subprocess.Popen(splitbin+" -i '"+filename+"' 2>&1 | grep 'Duration'",
shell = True,
stdout = subprocess.PIPE
).stdout.read()
print output
matches = re_length.search(output)
if matches:
video_length = int(matches.group(1)) * 3600 + \
int(matches.group(2)) * 60 + \
int(matches.group(3))
print "Video length in seconds: "+str(video_length)
else:
print "Can't determine video length."
raise SystemExit
if equal:
split_count = int(math.ceil(video_length/float(split_length)))
if(split_count == 1):
print "Video length is less then the target split length."
raise SystemExit
split_cmd = splitbin + " -i '"+filename+"' -vcodec copy "
for n in range(0, split_count):
split_str = ""
if n == 0:
split_start = 0
else:
split_start = split_length * n
split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \
" '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \
"'"
print "About to run: "+split_cmd+split_str
output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
subprocess.PIPE).stdout.read()
else:
if(len (split_points) <= 1):
print "There aren't at least two indices in cuefile."
raise SystemExit
split_cmd = splitbin + " -i '"+filename+"' -codec copy " # Enable audio, too
n = 0
split_points.append(-1)
split_start = split_points [0]
for split_end in split_points[1:]:
split_str = " -ss "+str(split_start)+((" -t "+str(split_end - split_start)) if split_end != -1 else "") + \
" '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \
"'" #Omit -t when last piece will be created
print "About to run: "+split_cmd+split_str
output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
subprocess.PIPE).stdout.read()
n += 1
split_start = split_end
def parse_options():
parser = OptionParser()
parser.add_option("-f", "--file",
dest = "filename",
help = "file to split, for example sample.avi",
type = "string",
action = "store"
)
parser.add_option("-s", "--split-size",
dest = "split_size",
help = "split or chunk size in seconds, for example 10; if 0 is given, -f refers to a cuefile",
type = "int",
action = "store"
)
(options, args) = parser.parse_args()
if options.filename and (options.split_size != None):
return (options.filename, options.split_size)
else:
parser.print_help()
raise SystemExit
if __name__ == '__main__':
try:
main()
except Exception, e:
print "Exception occured running main():"
print str(e)
This isn't fairly tested and should give only the idea.
If the equidistantly splitting would be done in a slighty other way (namely by first building a list of split_starts and split_length or better split_ends and then doing the actual job), there could be less excess code for both if-cases.
It uses -s=0 as flag to interpret -f as cuefile; this may seem to be unaesthetic.
I used it to split m4a sound-only files, therefore I got to change from "-vcodec" to "-acodec". Because just "-codec" also worked, I just left it. I don't know what the impact would be to actual videos. I left the equidistant part, it still uses "-vcodec" for now.
Finally, as my system uses avconv instead of ffmpeg, I put its name into a variable to be able to simply change it in the source. Another idea: Retrieve file name of script (don't know if this is possible under python like it can be done under bash by retrieving argument no. 0), chop off the "-split.py" part and use the remaining as tool’s name – so you’d use "ffmpeg-split.py" whereas I’d rename it to "avconv-split.py".
I haven't tracked down it thoroughly, but I'm suspiciously wondering if your code possibly omits the last fraction of seconds of the source video, because it handles only integer seconds.
Thanks – Peter
iOS app Mobile VR Station 3.14 has limit in the free version of 5 minutes per video.
So, I wanted to split my video into 5 min chinks to watch before purchasing a license.
Unfortunately, resulting videos can't be played, while the original was playing just fine. I've tried -v libx264
option with no luck.
Workaround for me was to use bandicam.
(I'm not affiliated with any of them in any way)
Here's the codec info of the original video as reported by VLC:
Codec info for chunks produced by this project was the same but lacked Color ...
and Chroma location
info.
While bandicam produced chunks with exactly the same codec info as the original.
Tried to run
python ffmpeg-split.py -f Myvideo.mp4 -m manifest.gun
got
File "ffmpeg-split.py", line 7
^
SyntaxError: invalid syntax
Is this a python release problem or ?
Gunnar
Hmmm some text did not show above. Lets see if this works
File "ffmpeg-split.py", line 7 <!DOCTYPE html> ^ SyntaxError: invalid syntax
I've followed the steps and this error message shows up
The previous threads about this error didn't help me out. The error message is misleading cause it's not about the video file specified in -f
option, it's actually about Python not being able to invoke ffmpeg.
The solution that worked for me was this one: https://stackoverflow.com/a/64458721/494058
Open Anaconda Prompt, then run:
conda install ffmpeg
Once setup is complete, you should be able to run python ffmpeg-split.py -f GOPR7098.MP4 -s 180
Do you think it's worth adding this to README.md? Maybe a one-liner to verify whether ffmpeg is installed and accessible
i am using this command - python3 ffmpeg-split.py -f 'somevideo.mkv' -S 4194304000
whereby i intend to split the video under 4000 MB ( = 4194304000 bytes ) but the resulting output creates splits with filesizes like 3200-3300 MB . i know its meant to be approximate but 20-25% variation feels bit too much . Is there any way to make it split closer to the -S filesize passed ?
I'm using python 3.8 on windows 10 and I went to open the help prompt in cmd and the program kept giving me error codes, so I had to manually edit all the print statements and added back the () so it would run. I'm not sure why it messed up but it did. The attached file is the print statement edited properly ig
hope this helps
Tried various options but I always get file not found error.
Does it work with python 3.x ?
I am 100% sure I am providing a valid file path.
I'm getting some errors like:
print "Format not supported. File must be a csv or json file"
^
SyntaxError: Missing parentheses in call to 'print'
Hi All,
I am using this utility to split videos. I am able to split the videos , however the first few seconds of the video are blank for some reason. Can you please help me out.
Thanks and Regards,
Shridhar
Hey there I'm getting similar errors
I'm using python to be precise Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:34:34) [MSC v.1928 32 bit (Intel)] on win32
I am using the windows terminal. I cd
ed into my directory and I ran the file on my python environment using & "C:/Program Files/Python38-32/python.exe" ffmpeg-split.py -f xp.mp4 -s 1800
which is same as python ffmpeg-split.py -f xp.mp4 -s 1800
on the terminal.
I got a similar error. I tried providing the absolute path to my file using & "C:/Program Files/Python38-32/python.exe" ffmpeg-split.py -f "E://ds//AARM-018//xp.mp4" -s 1800
but still got same error.
The exact log is as follows:
Traceback (most recent call last):
File "ffmpeg-split.py", line 225, in <module>
main()
File "ffmpeg-split.py", line 221, in main
split_by_seconds(video_length=video_length, **options.__dict__)
File "ffmpeg-split.py", line 97, in split_by_seconds
video_length = get_video_length(filename)
File "ffmpeg-split.py", line 78, in get_video_length
output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of",
File "C:\Program Files\Python38-32\lib\subprocess.py", line 415, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:\Program Files\Python38-32\lib\subprocess.py", line 493, in run
with Popen(*popenargs, **kwargs) as process:
File "C:\Program Files\Python38-32\lib\subprocess.py", line 858, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Program Files\Python38-32\lib\subprocess.py", line 1311, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified
So I looked closely around line 78
def get_video_length(filename):
output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of",
"default=noprint_wrappers=1:nokey=1", filename)).strip()
Since I was running things on terminal, I tried setting shell=True
as an end attribute just like:
def get_video_length(filename):
output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of",
"default=noprint_wrappers=1:nokey=1", filename), shell=True).strip()
This is when I get this subprocess.CalledProcessError: Command '('ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', 'E://ds//AARM-018//xp.mp4')' returned non-zero exit status 1.
Then I realized I messed things up for the worse. Any ideas regarding my issue will be appreciated!
when i try to split various video (mp4 or webm) i get this error message:
"can't determine video lenght"
Hi there,
I split file into equal duration but file sizes are different. I need them to be equal sizes (for uploading restrictions). It does not seem to be possible as yet. Any easy way to implement it?
Add support for splitting videos into unequal chunks with random duration, for example, i can limit the duration between 20s ~3m
Hello, thanks for your hard working,
I'm wondering, could this py make a different video file output floder?
thanks!
hello,
I'm wondering Can the video file name put it in the end?
thank you!
Hello @c0decracker, I'd like to update the video-splitter
since it does - to some extent - what I am attempting to do. In order to start working on the base code though, I I've done some updates to the style in order to make it easier to understand and modify.
A rough order I am following is:
video-splitter
in distributed configurationNowadays, a lot of Ubuntu distributions use avconv instead of ffmpeg. Inteface is almost identical. It would be great to have avconv working as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.