Save Selection As JPEG - Quality Options?

Started by Dave9, February 28, 2025, 01:57:45 AM

Previous topic - Next topic

Dave9

The few times I used the menu option, "Save Selection as JPEG", since it was JPEG I had just assumed it was a very high quality preset, but today I discovered that it seems to be closer to an amount of compression some apps call quality # 85?

I can't find any menu settings to change this.  Is there a workaround, or if not, could the option be put into a newer version of  Avidemux to save at a higher quality level or PNG instead of JPG? 

I'm aware that there is at least one way to do that, with ffmpeg command line, but that's quite clunky, cumbersome to do if Avidemux could just allow PNG?

eumagga0x2a

Avidemux uses the libavcodec default for (M)JPEG which is the highest quality.

Exporting selection as PNG images wastes a huge amount of disk space, can be accomplished via a script

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

if not ed.nbSegments():
    ui.displayError("No video", "Please load a video prior to running this script")
    return 0

start = adm.markerA
end = adm.markerB
if start > end:
    swap = end
    end = start
    start = swap

if not adm.setCurrentPts(start):
    ui.displayError("Seek error", "Cannot seek to the start of the selection")
    return 0

outfile = ui.fileWriteSelectEx("Select output filename", "png")
if outfile is None:
    return 0

def getTimeStampString(time):
    ct = int(time / 1000)
    mss = int(ct)
    mss -= int(mss / 1000) * 1000
    msecondsString = str(mss)

    if mss < 100:
        msecondsString = "0" + msecondsString

    if mss < 10:
        msecondsString = "0" + msecondsString

    ct /= 1000
    ss = int(ct)
    ss -= int(ss / 60) * 60
    secondsString = str(ss)
    if ss < 10:
        secondsString = "0" + secondsString

    ct /= 60
    mm = int(ct)
    mm -= int(mm / 60) * 60
    minutesString = str(mm)
    if mm < 10:
        minutesString = "0" + minutesString

    ct /= 60
    hh = int(ct)
    hoursString = str(hh)
    if hh < 10:
        hoursString = "0" + hoursString

    timestamp = hoursString + "h-" + minutesString + "m-" + secondsString + "s-" + msecondsString + "ms"
    return timestamp

count = 0
fileNameNoExtension = (splitext(outfile))[0]

while True:
    pts = ed.getCurrentPts()
    if pts >= end:
        break
    if not adm.savePng(fileNameNoExtension + "-" + getTimeStampString(pts) + ".png"):
        break
    count += 1
    if not adm.seekFrame(1):
        break

if not count:
    ui.displayError("Error", "No PNG images saved")
    return 0

ui.displayInfo("Finished", str(count) + " PNG images saved")
return count

Put it with .py as filename extension into the "custom" subfolder of Avidemux profile directory to make it accessible via menu.

Dave9

#2
Thank you for the script!

One question though, I am trying to later load these back into Avidemux in sequence, and if I understand correctly, they need to be in a single digit numerical sequence to be able to just pick the first frame and have Avidemux load successive files as frames, for  example 1.png, 2.png, 3.png? 

With the output of that script, it is not doing that.  Is there some other code I can put on this line (or elsewhere) to name the images in consecutive order?

if not adm.savePng(fileNameNoExtension + "-" + getTimeStampString(pts) + ".png"):

I'm not good at python and tried adding these lines and altering the adm.savePng line as shown below, but that just created an error message.  Obviously I don't know what I'm doing.  :)

def next_file_name():
    num = 1
    while True:
        file_name = '%d' % num
        if not os.path.exists(file_name):
            return file_name
        num += 1


while True:
    pts = ed.getCurrentPts()
    if pts >= end:
        break
    if not adm.savePng(next_file_name + ".png"):
        break
    count += 1
    if not adm.seekFrame(1):
        break

A bit of  background on what I'm  trying to achieve is to make video play in reverse, so after I have the sequential file names, I run a batch job on them to rename in the opposite order, then can load the first sequence of images into Avidemux, then append the reverse named sequence of images to achieve that.  I can already accomplish that with the Save Selection As JPG file save method built into Avidemux, because it saves them consecutively named as (filename)-00001.jpg, (filename)-00002.jpg, etc.

If there is an easier way to do this, that would be interesting as well.

Dave9

#3
While I am still interested in what is wrong with the code, I have found a workaround, which is to just run the batch job I use to create new, renamed files in reverse numerical order, and run that a second time on the reverse named files, to create a second set of files in the original order again, with sequential file names so Avidemux will load all in sequence.  Having to run the batch twice, does take twice as long, and twice as much storage space, but it's not a big problem for short time period video segments.

This is the batch file I use to do that:

@echo off
if not exist "reverse" mkdir reverse
del /Q "reverse\*"
SETLOCAL EnableDelayedExpansion
set /A var=10000
for /f "tokens=*" %%s in ('dir /b *.png ^| sort') do (
echo f | xcopy /f /y %%s reverse/!var!.png
set /A var-=1
)

del "reverse\10000.png"
pause

Dave9

#4
I would like to share my observations that started all this.

I loaded a video in Avidemux, use the Save Selection As JPEG on a frame.  215KB file size.

Next I ran this script to make a PNG on the same frame. 1.68MB

Next I loaded this PNG into an image editor and saved it at highest quality JPEG. 557KB

Next I loaded this PNG into a smartsaver app that lets you pick parameters as well.  781KB

In order to get that 1.68MB PNG down to a 215KB file size JPG, I have to set the smartsaver app, all the way down to quality 86 out of 100, to get about the same JPEG file size.

I am possibly being picky, but see the results where I have  zoomed in 20X to show the difference (and used pixel resizing, not bicubic resampling, to preserve the detail.  The default 215K JPG saved, has more artifacts than the larger filesize JPGs saved by the other apps, which have more than the PNG.

This is why I'd as soon just use PNG, temporary storage space is cheap/free.

You cannot view this attachment.

eumagga0x2a

There is no os class in tinyPy, if I am not mistaken.

Loading sequentially named images in Avidemux in reverse order: Edit -> Preferences -> Import -> Pictures -> [v] Load sequentially named pictures in reverse order

(I cannot use "x" for a checkmark as the forum software interprets it as a list)

I'll post a ready-to-use script with the desired output filename pattern later.

Avidemux invokes the MJPEG encoder in libavformat at default quality which is 2. It is possible to ask for 1, which generates output roughly 50% larger in size with almost no perceptible quality gain. I am not yet convinced this needs to be made tunable, the default is good enough for maybe 99% of users. However, extending the quality range for the MJPEG encoder definitely makes sense, thank you.


Dave9

#6
I had overlooked that setting for load sequentially named pictures in reverse order, thanks for pointing it out.

I don't feel like larger file size is an issue when dealing with short lengths of video, where the videos take up orders of magnitude more storage than a few thousands of pictures, temporarily stored then deleted once made back into a video.

eumagga0x2a

Here comes a version of the script which saves up to 99999 sequentially named PNG files from a selection:

adm = Avidemux()
ed = Editor()
ui = Gui()
mx = 99999
pad = "00000"

def zeropad(nb):
    c = int(nb)
    if c < 0 or c > mx:
        return "invalid"
    if not c:
        return pad
    a = 0
    while c > 0:
        a += 1
        c = int(c/10)
    return pad[a:] + str(nb)

if not ed.nbSegments():
    ui.displayError("No video", "Please load a video prior to running this script")
    return 0

start = adm.markerA
end = adm.markerB
if start > end:
    swap = end
    end = start
    start = swap

if not adm.setCurrentPts(start):
    ui.displayError("Seek error", "Cannot seek to the start of the selection")
    return 0

outfile = ui.fileWriteSelectEx("Select output filename", "png")
if outfile is None:
    return 0

count = 0
fileNameNoExtension = (splitext(outfile))[0]

while True:
    if ed.getCurrentPts() >= end:
        break
    if not adm.savePng(fileNameNoExtension + "-" + zeropad(count) + ".png"):
        break
    count += 1
    if count > mx:
        break
    if not adm.seekFrame(1):
        break

if not count:
    ui.displayError("Error", "No PNG images saved")
    return 0

ui.displayInfo("Finished", str(count) + " PNG images saved")
return count

eumagga0x2a

With future nightly builds, you should be able to save a selection to sequentially named JPG files with higher quality using the MJPEG encoder and the "Video only" RAW muxer: muxerRaw: add options to output a file per frame, to override extension.

Dave9

You must have the ultimate passion for this because your support level is outstanding.

Thank you.

Dave9

Quote from: eumagga0x2a on March 07, 2025, 06:12:58 PMHere comes a version of the script which saves up to 99999 sequentially named PNG files from a selection:



That you but something is going wrong.

I saved it as a .py script, chose it  on the custom menu choice, for a selection of video as usual, but it is only saving 36 PNG files, seemingly sequential frames, in a test where I selected 8 seconds worth of 29.97 FPS video.

eumagga0x2a

Was the target directory empty? The script should abort if there is a collision, if I am not mistaken. I tested it successfully outputting a few hundred PNG images for a selection of also roughly 8 seconds at 50 fps.

Dave9

#12
If collision means other files with same name, no there weren't. 

I just tried again, made an empty directory S:\test, and I was mistaken about 36 frames, it's making 37 counting the first (name)-00000.png

I recall once in the past, you stated that a script that works with one version of Avidemux may not work with another, when I had some scripts that stopped working after updating to a newer Avidemux.


Could this be the problem?  I'm using  ver. 2.8.2 r240601.   I just checked the nightly build folders and assuming it's the newest (?) will try avidemux_2.8.2 r241212_win64  when I get a chance.

Edit:  Okay I tried 2.8.2 r241212 and it is unusable for my purposes.  The prior r240601 just works without errors but when I installed it over top of the existing r240601, but now when I try to load a video with it, I get an error message titled avidemux.exe - No Disk, with the text box reading:  There is no disk in the drive.  Please insert a disk into drive \Device\Harddisk2\DR2"

I have to click cancel on that error message 4 times, then get a box titled avidemux and with text reading:  Exception Filter  The application has encountered a fatal problem.   The current editing has been saved and will be related at next start.

If I click show details on that box, it reads:

EXCEPTION_ACCESS_VIOLATION
unknown function  [unknown module]
ADM_setCrashHook  [libADM_core6.dll]
ADM_setCrashHook  [libADM_core6.dll]
ADM_setCrashHook  [libADM_core6.dll]
UnhandledExceptionFilter  [kernel32.dll]
MD5Final  [ntdll.dll]
_C_specific_handler  [ntdll.dll]
RtlDecodePointer  [ntdll.dll]
RtlUnwindEx  [ntdll.dll]
KiUserExceptionDispatcher  [ntdll.dll]

Lastly I then get a Microsoft Visual C++ Runtime Library titled error box that reads:  This application has requested the Runtime to terminate in an unusual way.  Please contact the application's support team for more information, and then a box that Avidemux has stopped working, with the following in that box:

Problem signature:
  Problem Event Name:   APPCRASH
  Application Name:   avidemux.exe
  Application Version:   2.8.2.24347
  Application Timestamp:   675a79da
  Fault Module Name:   avidemux.exe
  Fault Module Version:   2.8.2.24347
  Fault Module Timestamp:   675a79da
  Exception Code:   40000015
  Exception Offset:   0000000000066f66
  OS Version:   6.1.7601.2.1.0.256.1
  Locale ID:   1033
  Additional Information 1:   729b
  Additional Information 2:   729bf63e6f87e18addec5edfdb9fd72d
  Additional Information 3:   68f9
  Additional Information 4:   68f9ad1f8ca9a5386b5cbae12ea78f84

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt


I don't know if the 2nd error box message is related to the first, but i do know what is causing the No Disk message, which is a USB card reader, permanently connected in a computer case bay, that reserves the drive letter D:\ even with no media in it.   I have only come across this situation one time in the past, and that app could load without generating the No Disk error message by putting a flash card in the reader, or be reassigning the drive letter for it to be later in the alphabet like X:\, but reassignment is a bit trickier because I have some backup programs that handle USB flash drives and their drive letters get reassigned if I move the flash card reader off of D:\

I should also add that if I just try to load Avidemux from the start menu, rather than my normal method of right clicking on a file to bring up a context menu to Open With Avidemux, or my other usual method of dragging a file into Avidemux, then I don't see any of these error messages, but then once I use Avidemux's File - Open menu item, I again get the Exception Filter error message stated above, and then Avidemux closes.

I put a flash card in the D:\ reader and that got rid of the No Disk error, but the other errors remain, so will get back to it later.   It's starting to seem much  easier to just run my rename-files, batch job twice.  :)

Dave9

Another thing I wondered about, is whether that script needs a certain version of python to work?

eumagga0x2a

While I was doing previous testing on Linux with a local build off the latest code (including bundled FFmpeg updated to 7.1.1), now I retried on Windows 11 24H2 with official r241212 nightly and a 30000/1001 (29.97) fps video – both working flawlessly.

Mixing different Avidemux builds in a same directory and also running multiple Avidemux instances simultaneously is a known recipe for a disaster, please rule out that any of above may be the case.

Once I have solved or at least understood the issue of decoding errors with H.264 streams in MPEG-TS containers, I'll request a regeneration of the official environment for cross-compiling Avidemux, which should ultimately produce a working fresh nightly build.