News:

--

Main Menu

Navigating Segments in Tinypy

Started by TheTooleMan, July 23, 2022, 03:08:02 PM

Previous topic - Next topic

TheTooleMan

I've attempted this post half a dozen times but received the wrath of the overzealous spam detector. I will make another attempt now.

I record a two-hour block of cartoons with commercials each week. I load the recording into Avidemux and manually delete the commercials. This creates multiple segments in the same video.

My goal is to navigate through the collection of segments. For each segment, I want the procedure to set markerA and markerB, encode the video, and save an MKV file.

I am running into problems with the references to the properties of the segments. I don't understand the syntax shown in butterw's post 45 of the thread "[Tinypy] Tips & docs on Avidemux .py scripting."

more...

TheTooleMan

#1
My pasted code is rejected, so I will describe my attempts and errors instead.

Tinypy doesn't seem to be strongly typed, but apparently I should declare the type of variables used for the values of segmentIdx and the three "get" functions for segments. Please shed some light on these questions:

Can the Segments code posted in post 45 of the Tips and Docs post be pasted into my script and used as-is?

What type is pts?

Is there somewhere I can learn more about Tinypy syntax? (I asked this before, more or less.)

Here is the error produced by my script. The "len () of unsized object" seems to refer to segmentIDX or the value returned by getsegmentduration.

You cannot view this attachment.

Thanks for the help

butterw

Tinypy uses python syntax. You don't declare types of variables.

pts is an integer (in micro-seconds).






 

TheTooleMan

If I could paste my code into a message and not trigger the spam filter, you might see what I'm doing wrong. How can I do that?

eumagga0x2a

Please send me PM and I'll post it tomorrow for you in this topic. pts in Avidemux scripting is technically a double floating point value, but internally (in the C++ part), it is an unsigned 64-bit integer.

eumagga0x2a

Quote from: TheTooleMan on July 23, 2022, 03:08:02 PMI record a two-hour block of cartoons with commercials each week. I load the recording into Avidemux and manually delete the commercials.

Why? If there are no deletions within each cartoon, you could just save each one directly or, if you re-encode, use Ctrl+U to queue for later batch processing with Avidemux Jobs GUI.

TheTooleMan

Quote from: eumagga0x2a on July 25, 2022, 11:20:24 PM
Quote from: TheTooleMan on July 23, 2022, 03:08:02 PMI record a two-hour block of cartoons with commercials each week. I load the recording into Avidemux and manually delete the commercials.

Why? If there are no deletions within each cartoon, you could just save each one directly or, if you re-encode, use Ctrl+U to queue for later batch processing with Avidemux Jobs GUI.
Because a) a batch script saves me the time of waiting for each segment to be processed before moving to the next; b) thanks for the tip about the Jobs option; c) I don't re-encode; d) I want to learn the syntax and make this work, if possible; e) I'm not wasting any more time explaining myself to you. You either get it or you don't.

eumagga0x2a

Quote from: TheTooleMan on July 26, 2022, 02:05:14 PMc) I don't re-encode

I meant as the final stage. Performing editing steps and exporting segments in copy mode may complicate the task, triggering cut point checks and eventually making the actual start of the output differ from the provided selection start. Luckily, we don't need to take this complication into account here.

Below a project script which can either serve as a template for a fully-automated processing or be run directly as-is after editing steps have been completed. It will output each segment as a separate video to a target directory selected by the user.

The script has been tested on Linux only. If it doesn't work on Windows, please replace "/" in the argument for adm.save() with "\\".

#PY  <- Needed to identify #
#--automatically built--

adm = Avidemux()
ed=Editor()
gui=Gui()

# Populate the part below based on the project script
# exported once editing is finished.
# Audio-related commands may be completely omitted if
# there are no special wishes like track language etc.
#
# Alternatively, load a video, perform editing, select
# encoder etc, then run this script.
# ---------------------------------------------------
# if not adm.loadVideo("/path/to/video"):
#    raise("Cannot load /path/to/video")
#adm.audioClearTracks()
#adm.setSourceTrackLanguage(0,"eng")
#if adm.audioTotalTracksCount() <= 0:
#    raise("Cannot add audio track 0, total tracks: " + str(adm.audioTotalTracksCount()))
#adm.audioAddTrack(0)
#adm.audioCodec(0, "copy")
#adm.audioSetShift(0, 0, 0)
#adm.clearSegments()
#adm.addSegment(0, 17304033, 368451423)
#adm.addSegment(0, 427030022, 463262800)
#adm.addSegment(0, 1050285989, 443860078)
#adm.addSegment(0, 1639324433, 362645623)
#adm.addSegment(0, 2185019589, 416582833)
#adm.addSegment(0, 2657341433, 392925867)
#adm.addSegment(0, 3180330567, 406038966)
#adm.addSegment(0, 3640990767, 450733622)
#adm.addSegment(0, 4162027956, 438438000)
#adm.addSegment(0, 4820585856, 475007866)
#adm.addSegment(0, 5435850500, 446796356)
#adm.addSegment(0, 6110891533, 454287167)
#adm.addSegment(0, 6695542267, 481264122)

#adm.videoCodec("x265", "useAdvancedConfiguration=True", "general.params=AQ=21", "general.poolThreads=99", "general.frameThreads=0", "general.output_bit_depth=0", "general.preset=medium", "general.tuning=animation", "general.profile=main"
#    , "level=-1", "vui.sar_idc=1", "vui.sar_height=1", "vui.sar_width=1", "vui.color_primaries=1", "vui.transfer_characteristics=1", "vui.matrix_coeffs=1", "MaxRefFrames=5", "MinIdr=60", "MaxIdr=600", "i_scenecut_threshold=40"
#    , "MaxBFrame=5", "i_bframe_adaptive=2", "i_bframe_bias=0", "i_bframe_pyramid=1", "b_deblocking_filter=True", "b_open_gop=False", "interlaced_mode=0", "constrained_intra=False", "b_intra=True", "lookahead=40"
#    , "weighted_pred=2", "weighted_bipred=True", "rect_inter=False", "amp_inter=False", "limit_modes=False", "cb_chroma_offset=0", "cr_chroma_offset=0", "me_method=3", "me_range=32", "subpel_refine=6", "limit_refs=3"
#    , "rd_level=1", "psy_rd=0.400000", "rdoq_level=0", "psy_rdoq=0.000000", "fast_pskip=True", "dct_decimate=True", "noise_reduction_intra=0", "noise_reduction_inter=0", "strong_intra_smoothing=False", "ratecontrol.rc_method=0"
#    , "ratecontrol.qp_constant=0", "ratecontrol.qp_step=4", "ratecontrol.bitrate=0", "ratecontrol.vbv_max_bitrate=0", "ratecontrol.vbv_buffer_size=0", "ratecontrol.vbv_buffer_init=1", "ratecontrol.ip_factor=1.400000"
#    , "ratecontrol.pb_factor=1.300000", "ratecontrol.aq_mode=2", "ratecontrol.aq_strength=0.600000", "ratecontrol.cu_tree=True", "ratecontrol.strict_cbr=False")
# ---------------------------------------------------
# Replace muxer name and configuration below if desired so.
# In this case, please adjust the filename extension (ext).
adm.setContainer("MKV", "forceAspectRatio=False", "displayWidth=1280", "displayAspectRatio=2", "addColourInfo=False", "colMatrixCoeff=2", "colRange=0", "colTransfer=2", "colPrimaries=2")
ext = "mkv"

Counter = 0
mark1 = 0
mark2 = 0

nbSeg = ed.nbSegments()

if not nbSeg:
    gui.displayError("Error", "No video loaded, nothing to do, bye")
    return

if nbSeg > 100:
    gui.displayInfo("Warning", "Maximum of 100 segments supported, but got " + str(nbSeg))
    nbSeg = 100

filename = ed.getRefVideoName(0)
if filename is None:
    gui.displayError("Error", "Cannot obtain reference video filename")
    return

filename = (splitext(filename))[0]
filename = basename(filename)

if filename is None:
    gui.displayError("Error", "Cannot obtain input basename")
    return

# Replace gui.dirSelect() below with output directory path for unattended operation.
outdir = gui.dirSelect("Select output folder")
if outdir is None:
    gui.displayInfo("Warning", "No output folder selected, cannot proceed")
    return

leadingZero = ""

for segmentIdx in range(nbSeg):
    mark2 += ed.getDurationForSegment(segmentIdx)
    if segmentIdx < 10:
        leadingZero = "0"
    adm.markerA = mark1
    adm.markerB = mark2
    Counter += adm.save(outdir + "/" + filename + "-segment-" + leadingZero + str(segmentIdx) + "." + ext)
    mark1 = mark2

gui.displayInfo("Finished", str(Counter) + " files out of " + str(nbSeg) + " segments converted")