From c4500aa32420908de247b0a882596bfb7e90a3e6 Mon Sep 17 00:00:00 2001 From: Dave Date: Mon, 10 Aug 2020 01:57:52 -0400 Subject: [PATCH] Update docs --- docs/html/.buildinfo | 2 +- docs/html/_modules/acsuite.html | 41 +++++++++++++++------ docs/html/_modules/index.html | 4 +- docs/html/_static/documentation_options.js | 2 +- docs/html/genindex.html | 4 +- docs/html/index.html | 8 ++-- docs/html/objects.inv | Bin 283 -> 283 bytes docs/html/py-modindex.html | 4 +- docs/html/search.html | 4 +- docs/html/searchindex.js | 2 +- 10 files changed, 45 insertions(+), 26 deletions(-) diff --git a/docs/html/.buildinfo b/docs/html/.buildinfo index 0406037..eb9e22f 100644 --- a/docs/html/.buildinfo +++ b/docs/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 8083ae105364b70c5322521fb0238a67 +config: e1a4d8a52e5165c4be5c44f8bc7ae4d8 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/html/_modules/acsuite.html b/docs/html/_modules/acsuite.html index 9917c67..6ff1eb3 100644 --- a/docs/html/_modules/acsuite.html +++ b/docs/html/_modules/acsuite.html @@ -8,7 +8,7 @@ - acsuite — acsuite 5.1.0 documentation + acsuite — acsuite 5.2.0 documentation @@ -59,7 +59,7 @@
- 5.1.0 + 5.2.0
@@ -149,12 +149,13 @@

Source code for acsuite

 """Frame-based cutting/trimming/splicing of audio with VapourSynth and FFmpeg."""
 __all__ = ['eztrim']
 __author__ = 'Dave <orangechannel@pm.me>'
-__date__ = '3 August 2020'
+__date__ = '10 August 2020'
 __credits__ = """AzraelNewtype, for the original audiocutter.py.
 Ricardo Constantino (wiiaboo), for vfr.py from which this was inspired.
 doop, for explaining the use of None for empty slicing
+Vardë, for fixing FFmpeg's >4GB WAV file issues
 """
-__version__ = '5.1.0'
+__version__ = '5.2.0'
 
 import collections
 import fractions
@@ -183,6 +184,7 @@ 

Source code for acsuite

            *,
            ffmpeg_path: Optional[Path] = None,
            quiet: bool = False,
+           timecodes_file: Optional[Path] = None,
            debug: bool = False
            ) -> Optional[Dict[str, Union[int, List[int], List[str]]]]:
     """
@@ -226,6 +228,8 @@ 

Source code for acsuite

                         If ``ffmpeg`` exists in your `PATH`, it will automatically be detected and used.
 
     :param quiet:         Suppresses most console output from FFmpeg
+    :param timecodes_file: Timecodes v2 file (generated by vspipe, ffms2, etc.) for variable-frame-rate clips.
+                           Not needed for CFR clips.
     :param debug:         Used for testing purposes
     """
     if debug:
@@ -250,7 +254,7 @@ 

Source code for acsuite

             '.sbc',
             '.thd',
             '.tta',
-            '.wav',
+            '.wav', 'w64',
             '.wma',
         }
         if audio_file_ext not in ffmpeg_valid_encoder_extensions:
@@ -258,7 +262,7 @@ 

Source code for acsuite

             audio_file_ext = '.wav'
             codec_args = []
         else:
-            codec_args = ['-c:a', 'copy']
+            codec_args = ['-c:a', 'copy', '-rf64', 'auto']
 
         if outfile is None:
             outfile = audio_file_name + '_cut' + audio_file_ext
@@ -274,13 +278,16 @@ 

Source code for acsuite

             ffmpeg_path = which('ffmpeg')
         else:
             if not os.path.isfile(ffmpeg_path):
-                raise FileNotFoundError(f"ffmpeg executable at {ffmpeg_path} not found")
+                raise FileNotFoundError(f"eztrim: ffmpeg executable at {ffmpeg_path} not found")
             try:
                 args = ['ffmpeg', '-version']
                 if subprocess.run(args, stdout=subprocess.PIPE, text=True).stdout.split()[0] != 'ffmpeg':
-                    raise ValueError("ffmpeg executable not working properly")
+                    raise ValueError("eztrim: ffmpeg executable not working properly")
             except FileNotFoundError:
-                raise FileNotFoundError("ffmpeg executable not found in PATH") from None
+                raise FileNotFoundError("eztrim: ffmpeg executable not found in PATH") from None
+
+        if timecodes_file is not None and not os.path.isfile(timecodes_file):
+            raise FileNotFoundError(f"eztrim: {timecodes_file} not found")
 
     # error checking ------------------------------------------------------------------------
     if not isinstance(trims, (list, tuple)):
@@ -309,7 +316,7 @@ 

Source code for acsuite

     # --------------------------------------------
 
     num_frames = clip.num_frames
-    ts = functools.partial(f2ts, src_clip=clip)
+    ts = functools.partial(f2ts, timecodes_file=timecodes_file, src_clip=clip)
 
     if isinstance(trims, tuple):
         start, end = _negative_to_positive(num_frames, *trims)
@@ -358,10 +365,11 @@ 

Source code for acsuite

         os.remove(file)
-def f2ts(f: int, /, *, precision: int = 3, src_clip: vs.VideoNode) -> str: +def f2ts(f: int, /, *, precision: int = 3, timecodes_file: Optional[Path] = None, src_clip: vs.VideoNode) -> str: """Converts frame number to a timestamp based on framerate. Can handle variable-frame-rate clips as well, using similar methods to that of vspipe --timecodes. + For VFR clips, will use a timecodes v2 file if given, else will fallback to the slower frames() method. Meant to be called as a functools.partial with 'src_clip' specified before-hand. """ if precision not in [0, 3, 6, 9]: @@ -370,7 +378,11 @@

Source code for acsuite

         t = round(10 ** 9 * f * src_clip.fps ** -1)
         s = t / 10 ** 9
     else:
-        s = clip_to_timecodes(src_clip)[f]
+        if timecodes_file is not None:
+            timecodes = [float(x)/1000 for x in open(timecodes_file, 'r').read().splitlines()[1:]]
+            s = timecodes[f]
+        else:
+            s = clip_to_timecodes(src_clip)[f]
 
     m = s // 60
     s %= 60
@@ -392,9 +404,14 @@ 

Source code for acsuite

     """Cached function to return a list of timecodes for vfr clips."""
     timecodes = collections.deque([0.0], maxlen=src_clip.num_frames + 1)
     curr_time = fractions.Fraction()
+    init_percentage = 0
     for frame in src_clip.frames():
         curr_time += fractions.Fraction(frame.props['_DurationNum'], frame.props['_DurationDen'])
         timecodes.append(float(curr_time))
+        percentage_done = round(100 * len(timecodes) / src_clip.num_frames)
+        if percentage_done % 10 == 0 and percentage_done != init_percentage:
+            print(rf"Finding timecodes for variable-framerate clip: {percentage_done}% done")
+            init_percentage = percentage_done
     return timecodes
 
 
diff --git a/docs/html/_modules/index.html b/docs/html/_modules/index.html
index 3dc0a26..d7aaff1 100644
--- a/docs/html/_modules/index.html
+++ b/docs/html/_modules/index.html
@@ -8,7 +8,7 @@
   
   
   
-  Overview: module code — acsuite 5.1.0 documentation
+  Overview: module code — acsuite 5.2.0 documentation
   
 
   
@@ -59,7 +59,7 @@
             
             
               
- 5.1.0 + 5.2.0
diff --git a/docs/html/_static/documentation_options.js b/docs/html/_static/documentation_options.js index 59a603d..52ee168 100644 --- a/docs/html/_static/documentation_options.js +++ b/docs/html/_static/documentation_options.js @@ -1,6 +1,6 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '5.1.0', + VERSION: '5.2.0', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/docs/html/genindex.html b/docs/html/genindex.html index 47c1fa4..e487ff4 100644 --- a/docs/html/genindex.html +++ b/docs/html/genindex.html @@ -8,7 +8,7 @@ - Index — acsuite 5.1.0 documentation + Index — acsuite 5.2.0 documentation @@ -59,7 +59,7 @@
- 5.1.0 + 5.2.0
diff --git a/docs/html/index.html b/docs/html/index.html index 240f785..2533a42 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -8,7 +8,7 @@ - acsuite documentation — acsuite 5.1.0 documentation + acsuite documentation — acsuite 5.2.0 documentation @@ -59,7 +59,7 @@
- 5.1.0 + 5.2.0
@@ -157,7 +157,7 @@

acsuite documentation

Frame-based cutting/trimming/splicing of audio with VapourSynth and FFmpeg.

-acsuite.eztrim(clip, trims, audio_file, outfile=None, *, ffmpeg_path=None, quiet=False, debug=False)[source]
+acsuite.eztrim(clip, trims, audio_file, outfile=None, *, ffmpeg_path=None, quiet=False, timecodes_file=None, debug=False)[source]

Simple trimming function that follows VapourSynth/Python slicing syntax.

End frame is NOT inclusive.

For a 100 frame long VapourSynth clip:

@@ -202,6 +202,8 @@

acsuite documentation

ffmpeg_path (Union[bytes, PathLike, Path, str, None]) – Set this if ffmpeg is not in your PATH. If ffmpeg exists in your PATH, it will automatically be detected and used.

  • quiet (bool) – Suppresses most console output from FFmpeg

  • +
  • timecodes_file (Union[bytes, PathLike, Path, str, None]) – Timecodes v2 file (generated by vspipe, ffms2, etc.) for variable-frame-rate clips. +Not needed for CFR clips.

  • debug (bool) – Used for testing purposes

  • diff --git a/docs/html/objects.inv b/docs/html/objects.inv index ef220731f5e9922dd7bb74f9e81661ac4a410e24..c37a9de855c6c1558a5c574b818a9d3a82f5a594 100644 GIT binary patch delta 11 ScmbQuG@EIHEu+yyySo4tf&=FO delta 11 ScmbQuG@EIHEu-N?ySo4tegozJ diff --git a/docs/html/py-modindex.html b/docs/html/py-modindex.html index 639a519..dd54fd3 100644 --- a/docs/html/py-modindex.html +++ b/docs/html/py-modindex.html @@ -8,7 +8,7 @@ - Python Module Index — acsuite 5.1.0 documentation + Python Module Index — acsuite 5.2.0 documentation @@ -66,7 +66,7 @@
    - 5.1.0 + 5.2.0
    diff --git a/docs/html/search.html b/docs/html/search.html index 8ec4a9c..ac09686 100644 --- a/docs/html/search.html +++ b/docs/html/search.html @@ -8,7 +8,7 @@ - Search — acsuite 5.1.0 documentation + Search — acsuite 5.2.0 documentation @@ -60,7 +60,7 @@
    - 5.1.0 + 5.2.0
    diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js index bf71f54..76c3f11 100644 --- a/docs/html/searchindex.js +++ b/docs/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"":{acsuite:[0,0,0,"-"]},acsuite:{eztrim:[0,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:function"},terms:{"byte":0,"default":0,"function":0,"int":0,"long":0,"return":0,"true":[],For:0,NOT:0,The:0,These:0,Used:0,_cut:[],abl:[],almost:0,also:[],attemp:[],audio:0,audio_fil:0,audio_file_cut:0,automat:0,base:0,bdmv:[],blank:0,bool:0,can:0,clip:0,codec:[],consol:0,contain:[],core:0,cut:0,debug:0,detect:0,determin:0,dict:0,dictionari:[],directli:0,directoi:[],either:0,empti:0,encod:0,end:0,enter:0,execut:[],exist:0,ext:0,extens:0,eztrim:0,fals:0,ffmpeg:0,ffmpeg_path:0,ffms2:0,file:0,filenam:0,flac:[],follow:0,found:[],frame:0,framer:0,from:0,full:0,given:0,inclus:0,index:0,input:0,insert:0,instead:[],left:0,legaci:0,like:0,list:0,locat:0,losslessli:0,mastroka:[],mka:[],mkv:0,mkvmerg:[],mkvmerge_path:[],mkvtoolnix:[],most:0,must:0,need:0,neg:0,none:0,normal:0,num_fram:0,object:0,one:0,onli:[],option:0,otherwis:[],out:0,outfil:0,output:0,overwritten:0,page:[],paramet:0,path:0,pathlik:0,pcm:[],place:0,portabl:[],purpos:0,python:0,quiet:0,reason:0,recogn:0,recommend:0,refer:0,remux:[],repres:0,script:[],search:[],set:0,simpl:0,simpli:[],singl:0,skip:[],slice:0,sourc:0,specifi:[],splice:0,src:0,str:0,string:0,suppress:0,syntax:0,test:0,thi:0,timecod:0,track:[],trim:0,tupl:0,type:0,union:0,use:[],used:0,uses:[],valid:0,valu:[],vapoursynth:0,videonod:0,want:[],wav:0,write:[],you:0,your:0},titles:["acsuite documentation"],titleterms:{acsuit:0,document:0,footer:[]}}) \ No newline at end of file +Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,"sphinx.ext.todo":2,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"":{acsuite:[0,0,0,"-"]},acsuite:{eztrim:[0,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:function"},terms:{"byte":0,"default":0,"function":0,"int":0,"long":0,"return":0,"true":[],For:0,NOT:0,Not:0,The:0,These:0,Used:0,_cut:[],abl:[],almost:0,also:[],attemp:[],audio:0,audio_fil:0,audio_file_cut:0,automat:0,base:0,bdmv:[],blank:0,bool:0,can:0,cfr:0,clip:0,codec:[],consol:0,contain:[],core:0,cut:0,debug:0,detect:0,determin:0,dict:0,dictionari:[],directli:0,directoi:[],either:0,empti:0,encod:0,end:0,enter:0,etc:0,execut:[],exist:0,ext:0,extens:0,eztrim:0,fals:0,ffmpeg:0,ffmpeg_path:0,ffms2:0,file:0,filenam:0,flac:[],follow:0,found:[],frame:0,framer:0,from:0,full:0,gener:0,given:0,inclus:0,index:0,input:0,insert:0,instead:[],left:0,legaci:0,like:0,list:0,locat:0,losslessli:0,mastroka:[],mka:[],mkv:0,mkvmerg:[],mkvmerge_path:[],mkvtoolnix:[],most:0,must:0,need:0,neg:0,none:0,normal:0,num_fram:0,object:0,one:0,onli:[],option:0,otherwis:[],out:0,outfil:0,output:0,overwritten:0,page:[],paramet:0,path:0,pathlik:0,pcm:[],place:0,portabl:[],purpos:0,python:0,quiet:0,rate:0,reason:0,recogn:0,recommend:0,refer:0,remux:[],repres:0,script:[],search:[],set:0,simpl:0,simpli:[],singl:0,skip:[],slice:0,sourc:0,specifi:[],splice:0,src:0,str:0,string:0,suppress:0,syntax:0,test:0,thi:0,timecod:0,timecodes_fil:0,track:[],trim:0,tupl:0,type:0,union:0,use:[],used:0,uses:[],valid:0,valu:[],vapoursynth:0,variabl:0,videonod:0,vspipe:0,want:[],wav:0,write:[],you:0,your:0},titles:["acsuite documentation"],titleterms:{acsuit:0,document:0,footer:[]}}) \ No newline at end of file