├── LICENCE.txt ├── Languages ├── Languages │ ├── ar.properties │ ├── cs.properties │ ├── de.properties │ ├── en.properties │ ├── es.properties │ ├── fr.properties │ ├── hu.properties │ ├── it.properties │ ├── ja.properties │ ├── la.properties │ ├── nl.properties │ ├── pl.properties │ ├── pt_BR.properties │ ├── ru.properties │ ├── sl.properties │ ├── sv.properties │ ├── tr.properties │ ├── uk.properties │ ├── vi.properties │ ├── zh_CN.properties │ └── zh_TW.properties ├── ar.properties ├── cs.properties ├── de.properties ├── en.properties ├── es.properties ├── fr.properties ├── hu.properties ├── it.properties ├── ja.properties ├── la.properties ├── nl.properties ├── pl.properties ├── pt_BR.properties ├── ru.properties ├── sl.properties ├── sv.properties ├── tr.properties ├── uk.properties ├── vi.properties ├── zh_CN.properties └── zh_TW.properties ├── Library └── sources.txt ├── README.md ├── Shutter Encoder.jar ├── SocialBanner.png ├── fonts ├── FreeSans.ttf ├── Magneto.ttf ├── Montserrat.ttf └── NotoSansSC.otf ├── lib ├── activation.jar ├── commons-io-2.5.jar ├── commons-net-3.5.jar ├── flatlaf-3.5.2.jar ├── flatlaf-extras-3.5.2.jar ├── javax.mail.jar ├── jgoodies-common-1.8.0.jar ├── jgoodies-forms-1.8.0.jar ├── jnativehook-2.2.1.jar ├── jsoup-1.9.1.jar ├── jsvg-1.0.0.jar ├── pdfbox-app-2.0.28.jar ├── slf4j-api-1.7.9.jar ├── slf4j-simple-1.7.9.jar ├── swt-x86.jar └── swt.jar ├── logo.png └── src ├── application ├── Console.java ├── Donate.java ├── Ftp.java ├── Functions.java ├── GOP.java ├── GlobalKeyListener.java ├── HashGenerator.java ├── Informations.java ├── RecordInputDevice.java ├── ReducedWindow.java ├── Renamer.java ├── RenderQueue.java ├── SceneDetection.java ├── Settings.java ├── Shutter.java ├── Splash.java ├── SubtitlesEdit.java ├── SubtitlesEmbed.java ├── SubtitlesHelp.java ├── SubtitlesTimeline.java ├── Update.java ├── Utils.java ├── VideoPlayer.java ├── VideoWeb.java └── fileOverwriteWindow.java ├── contents ├── 2013-2016.jpg ├── arrow.svg ├── avid.png ├── check.svg ├── complete.wav ├── davinci.png ├── drop.svg ├── error.wav ├── generate.svg ├── help.svg ├── help_hover.svg ├── help_pressed.svg ├── icon.png ├── item.svg ├── list.svg ├── list_hover.svg ├── list_pressed.svg ├── lock.svg ├── mail.svg ├── max.svg ├── max_hover.svg ├── max_pressed.svg ├── new.svg ├── new_hover.svg ├── new_pressed.svg ├── pause.svg ├── play.svg ├── premiere.png ├── presets.svg ├── presets_hover.svg ├── presets_pressed.svg ├── preview.svg ├── preview_hover.svg ├── qrcode.png ├── quit.svg ├── quit_hover.svg ├── quit_pressed.svg ├── reduce.svg ├── reduce_hover.svg ├── reduce_pressed.svg ├── screenshot.svg ├── settings.svg ├── settings_hover.svg ├── settings_pressed.svg ├── stop.svg ├── stream.svg ├── unlock.svg └── volume.svg ├── functions ├── AudioEncoders.java ├── AudioNormalization.java ├── BlackDetection.java ├── Command.java ├── Conform.java ├── DVDRIP.java ├── Extract.java ├── FrameMD5.java ├── LoudnessTruePeak.java ├── Merge.java ├── OfflineDetection.java ├── Picture.java ├── ReplaceAudio.java ├── Rewrap.java ├── VMAF.java ├── VideoEncoders.java └── VideoInserts.java ├── library ├── BMXTRANSWRAP.java ├── DCRAW.java ├── DVDAUTHOR.java ├── EXIFTOOL.java ├── FFMPEG.java ├── FFPROBE.java ├── MEDIAINFO.java ├── NCNN.java ├── PDF.java ├── SEVENZIP.java ├── TSMUXER.java └── YOUTUBEDL.java └── settings ├── AdvancedFeatures.java ├── AudioSettings.java ├── BitratesAdjustement.java ├── Colorimetry.java ├── Corrections.java ├── Filter.java ├── FunctionUtils.java ├── Image.java ├── ImageSequence.java ├── InputAndOutput.java ├── Overlay.java ├── Timecode.java └── Transitions.java /Languages/Languages/cs.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/cs.properties -------------------------------------------------------------------------------- /Languages/Languages/de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/de.properties -------------------------------------------------------------------------------- /Languages/Languages/en.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/en.properties -------------------------------------------------------------------------------- /Languages/Languages/es.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/es.properties -------------------------------------------------------------------------------- /Languages/Languages/fr.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/fr.properties -------------------------------------------------------------------------------- /Languages/Languages/hu.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/hu.properties -------------------------------------------------------------------------------- /Languages/Languages/it.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/it.properties -------------------------------------------------------------------------------- /Languages/Languages/la.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/la.properties -------------------------------------------------------------------------------- /Languages/Languages/nl.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/nl.properties -------------------------------------------------------------------------------- /Languages/Languages/pl.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/pl.properties -------------------------------------------------------------------------------- /Languages/Languages/pt_BR.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/pt_BR.properties -------------------------------------------------------------------------------- /Languages/Languages/sv.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/sv.properties -------------------------------------------------------------------------------- /Languages/Languages/tr.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/tr.properties -------------------------------------------------------------------------------- /Languages/Languages/vi.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/Languages/vi.properties -------------------------------------------------------------------------------- /Languages/cs.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/cs.properties -------------------------------------------------------------------------------- /Languages/de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/de.properties -------------------------------------------------------------------------------- /Languages/en.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/en.properties -------------------------------------------------------------------------------- /Languages/es.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/es.properties -------------------------------------------------------------------------------- /Languages/fr.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/fr.properties -------------------------------------------------------------------------------- /Languages/hu.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/hu.properties -------------------------------------------------------------------------------- /Languages/it.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/it.properties -------------------------------------------------------------------------------- /Languages/la.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/la.properties -------------------------------------------------------------------------------- /Languages/nl.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/nl.properties -------------------------------------------------------------------------------- /Languages/pl.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/pl.properties -------------------------------------------------------------------------------- /Languages/pt_BR.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/pt_BR.properties -------------------------------------------------------------------------------- /Languages/sv.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/sv.properties -------------------------------------------------------------------------------- /Languages/tr.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/tr.properties -------------------------------------------------------------------------------- /Languages/vi.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Languages/vi.properties -------------------------------------------------------------------------------- /Library/sources.txt: -------------------------------------------------------------------------------- 1 | ffmpeg: ffmpeg.org 2 | 7za: www.7-zip.org 3 | exiftool: exiftool.org 4 | dcraw: www.dechifro.org/dcraw 5 | yt-dlp: github.com/yt-dlp/yt-dlp 6 | dvdauthor: dvdauthor.sourceforge.net 7 | tsMuxeR: github.com/justdan96/tsMuxer 8 | mediainfo: mediaarea.net/fr/MediaInfo 9 | bmxtranswrap: sourceforge.net/p/bmxlib/home/Home 10 | ncnn: https://github.com/xinntao/Real-ESRGAN-ncnn-vulkan 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Shutter Encoder v19.1

3 | 4 | ![logo](/SocialBanner.png) 5 | 6 | Download required [dependencies](../master/Library/sources.txt) into "Library" folder. 7 | 8 | Include [fonts](../master/fonts) with JRE. 9 | 10 | I'm using [Java version 20](https://jdk.java.net/20/) built using jlink: 11 | --compress 0 --strip-debug --no-header-files --no-man-pages --add-modules java.base,java.datatransfer,java.desktop,java.logging,java.security.sasl,java.xml,jdk.crypto.ec --output JRE 12 | 13 | ## Official website 14 | 15 | https://www.shutterencoder.com 16 | 17 | ### Builds 18 | 19 | https://www.shutterencoder.com/en/#downloads 20 | 21 | #### Changelog 22 | 23 | https://www.shutterencoder.com/changelog/ 24 | -------------------------------------------------------------------------------- /Shutter Encoder.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/Shutter Encoder.jar -------------------------------------------------------------------------------- /SocialBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/SocialBanner.png -------------------------------------------------------------------------------- /fonts/FreeSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/FreeSans.ttf -------------------------------------------------------------------------------- /fonts/Magneto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/Magneto.ttf -------------------------------------------------------------------------------- /fonts/Montserrat.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/Montserrat.ttf -------------------------------------------------------------------------------- /fonts/NotoSansSC.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/fonts/NotoSansSC.otf -------------------------------------------------------------------------------- /lib/activation.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/activation.jar -------------------------------------------------------------------------------- /lib/commons-io-2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/commons-io-2.5.jar -------------------------------------------------------------------------------- /lib/commons-net-3.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/commons-net-3.5.jar -------------------------------------------------------------------------------- /lib/flatlaf-3.5.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/flatlaf-3.5.2.jar -------------------------------------------------------------------------------- /lib/flatlaf-extras-3.5.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/flatlaf-extras-3.5.2.jar -------------------------------------------------------------------------------- /lib/javax.mail.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/javax.mail.jar -------------------------------------------------------------------------------- /lib/jgoodies-common-1.8.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jgoodies-common-1.8.0.jar -------------------------------------------------------------------------------- /lib/jgoodies-forms-1.8.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jgoodies-forms-1.8.0.jar -------------------------------------------------------------------------------- /lib/jnativehook-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jnativehook-2.2.1.jar -------------------------------------------------------------------------------- /lib/jsoup-1.9.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jsoup-1.9.1.jar -------------------------------------------------------------------------------- /lib/jsvg-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/jsvg-1.0.0.jar -------------------------------------------------------------------------------- /lib/pdfbox-app-2.0.28.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/pdfbox-app-2.0.28.jar -------------------------------------------------------------------------------- /lib/slf4j-api-1.7.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/slf4j-api-1.7.9.jar -------------------------------------------------------------------------------- /lib/slf4j-simple-1.7.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/slf4j-simple-1.7.9.jar -------------------------------------------------------------------------------- /lib/swt-x86.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/swt-x86.jar -------------------------------------------------------------------------------- /lib/swt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/lib/swt.jar -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/logo.png -------------------------------------------------------------------------------- /src/application/Donate.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package application; 21 | 22 | import java.awt.Color; 23 | import java.awt.Cursor; 24 | import java.awt.Desktop; 25 | import java.awt.Font; 26 | import java.awt.MouseInfo; 27 | import java.awt.Rectangle; 28 | import java.awt.event.MouseEvent; 29 | import java.awt.event.MouseListener; 30 | import java.awt.event.MouseMotionListener; 31 | import java.awt.geom.Area; 32 | import java.io.IOException; 33 | import java.net.URI; 34 | import java.net.URISyntaxException; 35 | 36 | import javax.swing.BorderFactory; 37 | import javax.swing.ImageIcon; 38 | import javax.swing.JFrame; 39 | import javax.swing.JLabel; 40 | import javax.swing.JPanel; 41 | import javax.swing.SwingConstants; 42 | import javax.swing.border.MatteBorder; 43 | 44 | import com.formdev.flatlaf.extras.FlatSVGIcon; 45 | 46 | public class Donate { 47 | 48 | private static int MousePositionX; 49 | private static int MousePositionY; 50 | 51 | public Donate() { 52 | 53 | JFrame frame = new JFrame(); 54 | frame.getContentPane().setBackground(Utils.bg32); 55 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 56 | frame.setTitle("Thanks!"); 57 | frame.setBackground(Utils.bg32); 58 | frame.setForeground(Color.WHITE); 59 | frame.getContentPane().setLayout(null); 60 | frame.setSize(280, 335); 61 | 62 | frame.setResizable(false); 63 | frame.setUndecorated(true); 64 | frame.getRootPane().setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, new Color(45,45,45))); 65 | Area shape1 = new Area(new AntiAliasedRoundRectangle(0, 0, frame.getWidth(), frame.getHeight(), 15, 15)); 66 | Area shape2 = new Area(new Rectangle(0, frame.getHeight()-15, frame.getWidth(), 15)); 67 | shape1.add(shape2); 68 | frame.setShape(shape1); 69 | frame.setAlwaysOnTop(true); 70 | 71 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage()); 72 | frame.setLocation(Shutter.frame.getX() + (Shutter.frame.getWidth() - frame.getWidth()) / 2, Shutter.frame.getY() + (Shutter.frame.getHeight() / 2 - frame.getHeight())); 73 | 74 | JPanel topPanel = new JPanel(); 75 | topPanel.setLayout(null); 76 | topPanel.setBackground(Utils.bg32); 77 | topPanel.setBounds(0, 0, frame.getWidth(), 28); 78 | 79 | JLabel quit = new JLabel(new FlatSVGIcon("contents/quit.svg", 15, 15)); 80 | quit.setHorizontalAlignment(SwingConstants.CENTER); 81 | quit.setBounds(frame.getSize().width - 20, 4, 15, 15); 82 | topPanel.add(quit); 83 | 84 | quit.addMouseListener(new MouseListener() { 85 | 86 | private boolean accept = false; 87 | 88 | @Override 89 | public void mouseClicked(MouseEvent e) { 90 | } 91 | 92 | @Override 93 | public void mousePressed(MouseEvent e) { 94 | 95 | quit.setIcon(new FlatSVGIcon("contents/quit_pressed.svg", 15, 15)); 96 | accept = true; 97 | } 98 | 99 | @Override 100 | public void mouseReleased(MouseEvent e) { 101 | 102 | if (accept) 103 | { 104 | System.exit(0); 105 | } 106 | } 107 | 108 | @Override 109 | public void mouseEntered(MouseEvent e) { 110 | quit.setIcon(new FlatSVGIcon("contents/quit_hover.svg", 15, 15)); 111 | } 112 | 113 | @Override 114 | public void mouseExited(MouseEvent e) { 115 | quit.setIcon(new FlatSVGIcon("contents/quit.svg", 15, 15)); 116 | accept = false; 117 | } 118 | 119 | }); 120 | 121 | JLabel title = new JLabel(frame.getTitle()); 122 | title.setHorizontalAlignment(JLabel.CENTER); 123 | title.setBounds(0, 1, frame.getWidth(), 24); 124 | title.setFont(new Font(Shutter.mainFont, Font.PLAIN, 17)); 125 | topPanel.add(title); 126 | 127 | JLabel topImage = new JLabel(); 128 | topImage.setBackground(new Color(35,35,40)); 129 | topImage.setOpaque(true); 130 | topImage.setBorder(new MatteBorder(1, 0, 1, 0, new Color(45,45,45))); 131 | topImage.setBounds(0, 0, topPanel.getWidth(), 24); 132 | topPanel.add(topImage); 133 | 134 | topImage.addMouseListener(new MouseListener() { 135 | 136 | @Override 137 | public void mouseClicked(MouseEvent down) { 138 | } 139 | 140 | @Override 141 | public void mousePressed(MouseEvent down) { 142 | MousePositionX = down.getPoint().x; 143 | MousePositionY = down.getPoint().y; 144 | } 145 | 146 | @Override 147 | public void mouseReleased(MouseEvent e) { 148 | } 149 | 150 | @Override 151 | public void mouseEntered(MouseEvent e) { 152 | } 153 | 154 | @Override 155 | public void mouseExited(MouseEvent e) { 156 | } 157 | 158 | }); 159 | 160 | topImage.addMouseMotionListener(new MouseMotionListener(){ 161 | 162 | @Override 163 | public void mouseDragged(MouseEvent e) { 164 | frame.setLocation(MouseInfo.getPointerInfo().getLocation().x - MousePositionX, MouseInfo.getPointerInfo().getLocation().y - MousePositionY); 165 | } 166 | 167 | @Override 168 | public void mouseMoved(MouseEvent e) { 169 | } 170 | 171 | }); 172 | 173 | frame.getContentPane().add(topPanel); 174 | 175 | JLabel qrcode = new JLabel(); 176 | qrcode.setIcon(new ImageIcon(getClass().getClassLoader().getResource("contents/qrcode.png"))); 177 | qrcode.setHorizontalAlignment(SwingConstants.CENTER); 178 | qrcode.setBounds((frame.getWidth() - 250) / 2, topPanel.getHeight() + 10, 250, 250); 179 | frame.getContentPane().add(qrcode); 180 | 181 | qrcode.addMouseListener(new MouseListener() { 182 | 183 | @Override 184 | public void mouseClicked(MouseEvent arg0) { 185 | try { 186 | Desktop.getDesktop().browse(new URI("https://donate.stripe.com/28o29m0QwfRZ4U0cMM")); 187 | } catch (IOException | URISyntaxException e) {} 188 | 189 | System.exit(0); 190 | } 191 | 192 | @Override 193 | public void mouseEntered(MouseEvent arg0) { 194 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 195 | } 196 | 197 | @Override 198 | public void mouseExited(MouseEvent arg0) { 199 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 200 | } 201 | 202 | @Override 203 | public void mousePressed(MouseEvent arg0) { 204 | } 205 | 206 | @Override 207 | public void mouseReleased(MouseEvent arg0) { 208 | } 209 | 210 | }); 211 | 212 | JLabel line1 = new JLabel("Hope you enjoyed the software!"); 213 | line1.setHorizontalAlignment(SwingConstants.CENTER); 214 | line1.setSize(frame.getWidth(), 16); 215 | line1.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12)); 216 | line1.setLocation((frame.getWidth() - line1.getWidth()) / 2, qrcode.getY() + qrcode.getHeight() + 7); 217 | frame.getContentPane().add(line1); 218 | 219 | JLabel line2 = new JLabel("Support me to make it even better!"); 220 | line2.setHorizontalAlignment(SwingConstants.CENTER); 221 | line2.setSize(frame.getWidth(), 16); 222 | line2.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12)); 223 | line2.setLocation((frame.getWidth() - line2.getWidth()) / 2, line1.getY() + line1.getHeight()); 224 | frame.getContentPane().add(line2); 225 | 226 | frame.setVisible(true); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/application/GOP.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package application; 21 | 22 | import java.awt.Color; 23 | import java.awt.Component; 24 | import java.awt.Font; 25 | import java.awt.event.AdjustmentEvent; 26 | import java.awt.event.AdjustmentListener; 27 | import java.awt.event.WindowEvent; 28 | import java.awt.event.WindowListener; 29 | import java.io.File; 30 | 31 | import javax.swing.ImageIcon; 32 | import javax.swing.JDialog; 33 | import javax.swing.JFrame; 34 | import javax.swing.JLabel; 35 | import javax.swing.JScrollBar; 36 | import javax.swing.SwingConstants; 37 | 38 | import library.FFPROBE; 39 | 40 | public class GOP { 41 | 42 | public static JDialog frame; 43 | private JScrollBar scrollBar; 44 | 45 | public GOP() { 46 | 47 | frame = new JDialog(); 48 | frame.setResizable(false); 49 | frame.setModal(false); 50 | frame.setForeground(Color.WHITE); 51 | frame.getContentPane().setLayout(null); 52 | frame.getContentPane().setBackground(Utils.bg32); 53 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 54 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage()); 55 | 56 | scrollBar = new JScrollBar(); 57 | scrollBar.setOrientation(JScrollBar.HORIZONTAL); 58 | scrollBar.setVisible(true); 59 | scrollBar.setBackground(Utils.c30); 60 | frame.getContentPane().add(scrollBar); 61 | 62 | scrollBar.addAdjustmentListener(new AdjustmentListener(){ 63 | 64 | public void adjustmentValueChanged(AdjustmentEvent ae) { 65 | if (scrollBar.getValueIsAdjusting()) 66 | { 67 | int i = 12; 68 | for (Component c : frame.getContentPane().getComponents()) 69 | { 70 | if (c instanceof JLabel) 71 | { 72 | c.setLocation(i - scrollBar.getValue(), 12); 73 | i += 112; 74 | } 75 | } 76 | } 77 | } 78 | 79 | }); 80 | 81 | JLabel image1 = new JLabel("I"); 82 | image1.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40)); 83 | image1.setHorizontalAlignment(SwingConstants.CENTER); 84 | image1.setBackground(new Color(232,67,67)); 85 | image1.setOpaque(true); 86 | image1.setForeground(Color.BLACK); 87 | image1.setBounds(12, 12, 100, 100); 88 | frame.getContentPane().add(image1); 89 | 90 | File fichier = new File(Shutter.fileList.getSelectedValue()); 91 | 92 | FFPROBE.AnalyzeGOP(fichier.toString(), true); 93 | 94 | do { 95 | try { 96 | Thread.sleep(100); 97 | } catch (InterruptedException e) {} 98 | } while (FFPROBE.isRunning); 99 | 100 | frame.setTitle(Shutter.language.getProperty("analyzeOf") + " " + fichier.getName() + " | GOP " + Shutter.language.getProperty("of") + " " + FFPROBE.gopCount); 101 | 102 | if (FFPROBE.gopCount <= 12) 103 | { 104 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 105 | frame.setSize(FFPROBE.gopSpace + 8, 154); 106 | else 107 | frame.setSize(FFPROBE.gopSpace + 8 + 10, 164); 108 | 109 | scrollBar.setVisible(false); 110 | } 111 | else if (FFPROBE.gopSpace + 8 > 1476) 112 | { 113 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 114 | frame.setSize(1476, 171); 115 | else 116 | frame.setSize(1486, 181); 117 | 118 | scrollBar.setVisible(true); 119 | } 120 | else 121 | { 122 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 123 | frame.setSize(FFPROBE.gopSpace + 8, 171); 124 | else 125 | frame.setSize(FFPROBE.gopSpace + 8 + 10, 181); 126 | scrollBar.setVisible(true); 127 | } 128 | 129 | frame.setLocation(Shutter.frame.getLocation().x + (Shutter.frame.getSize().width / 2) - (frame.getSize().width / 2), Shutter.frame.getLocation().y + 150); 130 | 131 | scrollBar.setBounds(0, 125, frame.getSize().width - 6, 17); 132 | scrollBar.setMaximum((112 * (FFPROBE.gopCount - 12) + 8)); 133 | 134 | frame.addWindowListener(new WindowListener(){ 135 | 136 | @Override 137 | public void windowActivated(WindowEvent arg0) { 138 | } 139 | 140 | @Override 141 | public void windowClosed(WindowEvent arg0) { 142 | frame.getContentPane().removeAll(); 143 | } 144 | 145 | @Override 146 | public void windowClosing(WindowEvent arg0) { 147 | 148 | } 149 | 150 | @Override 151 | public void windowDeactivated(WindowEvent arg0) { 152 | } 153 | 154 | @Override 155 | public void windowDeiconified(WindowEvent arg0) { 156 | } 157 | 158 | @Override 159 | public void windowIconified(WindowEvent arg0) { 160 | } 161 | 162 | @Override 163 | public void windowOpened(WindowEvent arg0) { 164 | } 165 | 166 | }); 167 | 168 | frame.setVisible(true); 169 | } 170 | 171 | public static void newImage(char type, int gopSpace) 172 | { 173 | JLabel image; 174 | if (type == 'I') 175 | { 176 | image = new JLabel("I"); 177 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40)); 178 | image.setHorizontalAlignment(SwingConstants.CENTER); 179 | image.setForeground(Color.BLACK); 180 | image.setBackground(new Color(232,67,67)); 181 | image.setOpaque(true); 182 | } 183 | else if (type == 'P') 184 | { 185 | image = new JLabel("P"); 186 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40)); 187 | image.setHorizontalAlignment(SwingConstants.CENTER); 188 | image.setForeground(Color.BLACK); 189 | image.setBackground(new Color(68,139,233)); 190 | image.setOpaque(true); 191 | } 192 | else 193 | { 194 | image = new JLabel("B"); 195 | image.setFont(new Font(Shutter.mainFont, Font.PLAIN, 40)); 196 | image.setHorizontalAlignment(SwingConstants.CENTER); 197 | image.setForeground(Color.BLACK); 198 | image.setBackground(new Color(100,232,67)); 199 | image.setOpaque(true); 200 | } 201 | image.setSize(100, 100); 202 | image.setLocation(gopSpace, 12); 203 | frame.getContentPane().add(image); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/application/GlobalKeyListener.java: -------------------------------------------------------------------------------- 1 | /* JNativeHook: Global keyboard and mouse hooking for Java. 2 | * Copyright (C) 2006-2015 Alexander Barker. All Rights Received. 3 | * https://github.com/kwhat/jnativehook/ 4 | * 5 | * JNativeHook is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published 7 | * by the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * JNativeHook is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package application; 20 | 21 | import com.github.kwhat.jnativehook.GlobalScreen; 22 | import com.github.kwhat.jnativehook.NativeHookException; 23 | import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent; 24 | import com.github.kwhat.jnativehook.keyboard.NativeKeyListener; 25 | 26 | public class GlobalKeyListener implements NativeKeyListener { 27 | public static boolean keyIsPressed = false; 28 | 29 | public void nativeKeyPressed(NativeKeyEvent e) { 30 | keyIsPressed = true; 31 | } 32 | 33 | public void nativeKeyReleased(NativeKeyEvent e) { 34 | keyIsPressed = false; 35 | } 36 | 37 | public void nativeKeyTyped(NativeKeyEvent e) { 38 | } 39 | 40 | public static void main(String[] args) { 41 | try { 42 | GlobalScreen.registerNativeHook(); 43 | } 44 | catch (NativeHookException ex) {} 45 | 46 | GlobalScreen.addNativeKeyListener(new GlobalKeyListener()); 47 | } 48 | } -------------------------------------------------------------------------------- /src/application/Splash.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package application; 21 | 22 | import java.awt.Color; 23 | import java.awt.Graphics; 24 | import java.awt.Graphics2D; 25 | import java.awt.Image; 26 | import java.awt.RenderingHints; 27 | 28 | import javax.swing.ImageIcon; 29 | import javax.swing.JWindow; 30 | 31 | @SuppressWarnings("serial") 32 | public class Splash extends JWindow { 33 | 34 | public static Graphics g; 35 | private static int loading = 0; 36 | Image splashScreen; 37 | 38 | public Splash() { 39 | 40 | splashScreen = new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage(); 41 | 42 | setBackground(new Color(0,0,0,0)); 43 | 44 | setSize(256, 256); 45 | 46 | setLocationRelativeTo(null); 47 | 48 | setVisible(true); 49 | 50 | if (System.getProperty("os.name").contains("Windows")) 51 | updateProgressBar(); 52 | } 53 | 54 | public void paint(Graphics g) { 55 | super.paint(g); 56 | 57 | RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); 58 | qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY ); 59 | ((Graphics2D) g).setRenderingHints(qualityHints); 60 | 61 | g.drawImage(splashScreen, 0, 0, this); 62 | g.setColor(Color.WHITE); 63 | g.drawRoundRect(26, 128, 200, 10, 10, 10); 64 | g.fillRoundRect(26, 128, loading, 10, 10, 10); 65 | 66 | if (System.getProperty("os.name").contains("Windows") == false) 67 | { 68 | do { 69 | g.fillRoundRect(26, 128, loading, 10, 10, 10); 70 | } while (Shutter.frame.isVisible() == false); 71 | 72 | dispose(); 73 | } 74 | } 75 | 76 | public static void increment() { 77 | loading += 7; 78 | if (loading > 200) 79 | loading = 200; 80 | } 81 | 82 | public void updateProgressBar() { 83 | 84 | Thread refresh = new Thread(new Runnable() { 85 | 86 | @Override 87 | public void run() { 88 | do { 89 | repaint(); 90 | try { 91 | Thread.sleep(10); 92 | } catch (InterruptedException e) {} 93 | } while (loading < 200); 94 | 95 | dispose(); 96 | } 97 | 98 | }); 99 | refresh.start(); 100 | } 101 | } -------------------------------------------------------------------------------- /src/application/SubtitlesHelp.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package application; 21 | 22 | import javax.swing.ImageIcon; 23 | import javax.swing.JFrame; 24 | import javax.swing.JTextPane; 25 | 26 | import java.awt.*; 27 | 28 | public class SubtitlesHelp { 29 | 30 | public static JFrame frame; 31 | 32 | public SubtitlesHelp() { 33 | 34 | frame = new JFrame(); 35 | frame.getContentPane().setLayout(null); 36 | frame.setResizable(false); 37 | frame.setTitle(Shutter.language.getProperty("frameSubtitles")); 38 | frame.getContentPane().setBackground(Utils.bg32); 39 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage()); 40 | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 41 | 42 | frame.setLocation(Shutter.frame.getLocation().x + Shutter.frame.getSize().width/2 - 200, Shutter.frame.getLocation().y + Shutter.frame.getHeight() /2 - 150); 43 | 44 | JTextPane lblHelp = new JTextPane(); 45 | lblHelp.setBackground(Utils.c30); 46 | lblHelp.setText(Shutter.language.getProperty("txtShortcuts")); 47 | lblHelp.setForeground(Color.WHITE); 48 | lblHelp.setHighlighter(null); 49 | lblHelp.setFocusable(false); 50 | lblHelp.setEditable(false); 51 | lblHelp.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12)); 52 | lblHelp.setBounds(10, 12, 420, 320); 53 | frame.getContentPane().add(lblHelp); 54 | 55 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 56 | frame.setSize(lblHelp.getWidth() + 10, lblHelp.getY() + lblHelp.getHeight()); 57 | else 58 | frame.setSize(lblHelp.getWidth() + 10, lblHelp.getY() + lblHelp.getHeight() + 10); 59 | 60 | frame.setVisible(true); 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/application/fileOverwriteWindow.java: -------------------------------------------------------------------------------- 1 | package application; 2 | 3 | import java.awt.Font; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | 7 | import javax.swing.ImageIcon; 8 | import javax.swing.JButton; 9 | import javax.swing.JCheckBox; 10 | import javax.swing.JDialog; 11 | 12 | public class fileOverwriteWindow { 13 | 14 | public static JCheckBox caseApplyToAll = new JCheckBox(Shutter.language.getProperty("caseApplyToAll")); 15 | public static String value; 16 | 17 | public fileOverwriteWindow(String file) { 18 | 19 | value = "cancel"; 20 | 21 | JDialog frame = new JDialog(); 22 | frame.setTitle(file + " " + Shutter.language.getProperty("alreadyExist").toLowerCase()); 23 | frame.setLayout(null); 24 | frame.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("contents/icon.png")).getImage()); 25 | frame.setResizable(false); 26 | frame.setModal(true); 27 | frame.getContentPane().setLayout(null); 28 | 29 | System.setProperty("apple.laf.useScreenMenuBar", "false"); 30 | 31 | JButton btnKeep = new JButton(Shutter.language.getProperty("btnKeep")); 32 | btnKeep.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12)); 33 | btnKeep.setBounds(7, 7, btnKeep.getPreferredSize().width, 21); 34 | frame.getContentPane().add(btnKeep); 35 | 36 | btnKeep.addActionListener(new ActionListener() { 37 | 38 | @Override 39 | public void actionPerformed(ActionEvent arg0) { 40 | 41 | value = "keep"; 42 | frame.dispose(); 43 | 44 | } 45 | 46 | }); 47 | 48 | JButton btnOverwrite = new JButton(Shutter.language.getProperty("btnOverwrite")); 49 | btnOverwrite.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12)); 50 | btnOverwrite.setBounds(btnKeep.getX() + btnKeep.getWidth() + 4, 7, btnOverwrite.getPreferredSize().width, 21); 51 | frame.getContentPane().add(btnOverwrite); 52 | 53 | btnOverwrite.addActionListener(new ActionListener() { 54 | 55 | @Override 56 | public void actionPerformed(ActionEvent arg0) { 57 | 58 | value = "overwrite"; 59 | frame.dispose(); 60 | 61 | } 62 | 63 | }); 64 | 65 | JButton btnSkip = new JButton(Shutter.language.getProperty("btnSkip")); 66 | btnSkip.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12)); 67 | btnSkip.setBounds(btnOverwrite.getX() + btnOverwrite.getWidth() + 4, 7, btnSkip.getPreferredSize().width, 21); 68 | frame.getContentPane().add(btnSkip); 69 | 70 | btnSkip.addActionListener(new ActionListener() { 71 | 72 | @Override 73 | public void actionPerformed(ActionEvent arg0) { 74 | 75 | value = "skip"; 76 | frame.dispose(); 77 | 78 | } 79 | 80 | }); 81 | 82 | JButton btnCancel = new JButton(Shutter.language.getProperty("btnCancel")); 83 | btnCancel.setFont(new Font(Shutter.boldFont, Font.PLAIN, 12)); 84 | btnCancel.setBounds(btnSkip.getX() + btnSkip.getWidth() + 4, 7, btnCancel.getPreferredSize().width, 21); 85 | frame.getContentPane().add(btnCancel); 86 | 87 | btnCancel.addActionListener(new ActionListener() { 88 | 89 | @Override 90 | public void actionPerformed(ActionEvent arg0) { 91 | 92 | frame.dispose(); 93 | 94 | } 95 | 96 | }); 97 | 98 | caseApplyToAll.setSelected(false); 99 | caseApplyToAll.setEnabled(true); 100 | caseApplyToAll.setFont(new Font(Shutter.mainFont, Font.PLAIN, 12)); 101 | caseApplyToAll.setBounds((btnCancel.getX() + btnCancel.getWidth() + 7 - caseApplyToAll.getPreferredSize().width) / 2, btnCancel.getY() + btnCancel.getHeight() + 4, caseApplyToAll.getPreferredSize().width, 23); 102 | frame.getContentPane().add(caseApplyToAll); 103 | 104 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 105 | { 106 | frame.setSize(btnCancel.getX() + btnCancel.getWidth() + 7, 90); 107 | } 108 | else 109 | frame.setSize(btnCancel.getX() + btnCancel.getWidth() + 17, 100); 110 | 111 | frame.setLocation(Shutter.frame.getX() + (Shutter.frame.getWidth() - frame.getWidth()) / 2, Shutter.frame.getY() + (Shutter.frame.getHeight()- frame.getHeight()) / 2); 112 | frame.setVisible(true); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/contents/2013-2016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/2013-2016.jpg -------------------------------------------------------------------------------- /src/contents/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/contents/avid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/avid.png -------------------------------------------------------------------------------- /src/contents/check.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/complete.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/complete.wav -------------------------------------------------------------------------------- /src/contents/davinci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/davinci.png -------------------------------------------------------------------------------- /src/contents/drop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/error.wav -------------------------------------------------------------------------------- /src/contents/generate.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 15 | 21 | 22 | -------------------------------------------------------------------------------- /src/contents/help.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/help_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/help_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/icon.png -------------------------------------------------------------------------------- /src/contents/item.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/contents/list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/contents/list_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/contents/list_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/contents/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/contents/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/max.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/contents/max_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/contents/max_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/contents/new.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/new_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/new_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/contents/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pause 5 | 6 | -------------------------------------------------------------------------------- /src/contents/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | play 5 | 6 | -------------------------------------------------------------------------------- /src/contents/premiere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/premiere.png -------------------------------------------------------------------------------- /src/contents/presets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/presets_hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/presets_pressed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/preview.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/contents/preview_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/contents/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulpacifico/shutter-encoder/6990bb7acfadfc7576e2654b1d399302e08de6f4/src/contents/qrcode.png -------------------------------------------------------------------------------- /src/contents/quit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/contents/quit_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/contents/quit_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/contents/reduce.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/contents/reduce_hover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/contents/reduce_pressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/contents/screenshot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/contents/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/settings_hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/settings_pressed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/contents/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | stop 5 | 6 | -------------------------------------------------------------------------------- /src/contents/stream.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/contents/unlock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/contents/volume.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/functions/BlackDetection.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.awt.FileDialog; 23 | import java.io.File; 24 | import java.io.FileNotFoundException; 25 | import java.io.PrintWriter; 26 | import java.io.UnsupportedEncodingException; 27 | 28 | import javax.swing.JOptionPane; 29 | 30 | import application.Shutter; 31 | import application.VideoPlayer; 32 | import library.FFMPEG; 33 | import settings.FunctionUtils; 34 | import settings.InputAndOutput; 35 | 36 | public class BlackDetection extends Shutter { 37 | 38 | public static void main() { 39 | 40 | Thread thread = new Thread(new Runnable(){ 41 | @Override 42 | public void run() { 43 | 44 | if (scanIsRunning == false) 45 | FunctionUtils.completed = 0; 46 | 47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 48 | 49 | for (int i = 0 ; i < liste.getSize() ; i++) 50 | { 51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 52 | 53 | if (file == null) 54 | break; 55 | 56 | try { 57 | 58 | String fileName = file.getName(); 59 | 60 | lblCurrentEncoding.setText(fileName); 61 | 62 | //Data analyze 63 | if (FunctionUtils.analyze(file, false) == false) 64 | continue; 65 | 66 | //InOut 67 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 68 | 69 | String levels = "0.1"; 70 | if (comboFilter.getSelectedIndex() == 1) 71 | levels = "0.0"; 72 | 73 | //Command 74 | String cmd; 75 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 76 | cmd = " -an -vf blackdetect=d=0.0:pix_th=" + levels + " -f null -"; 77 | else 78 | cmd = " -an -vf blackdetect=d=0.0:pix_th=" + levels + " -f null -" + '"'; 79 | 80 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd); 81 | 82 | do 83 | { 84 | Thread.sleep(100); 85 | } 86 | while(FFMPEG.runProcess.isAlive()); 87 | 88 | //Show detection 89 | if (cancelled == false) 90 | showDetection(fileName); 91 | 92 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 93 | { 94 | if (lastActions(file, fileName)) 95 | break; 96 | } 97 | 98 | } catch (InterruptedException e) { 99 | FFMPEG.error = true; 100 | } 101 | } 102 | 103 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 104 | enfOfFunction(); 105 | } 106 | 107 | }); 108 | thread.start(); 109 | 110 | } 111 | 112 | private static void showDetection(String fileName) { 113 | 114 | if (FFMPEG.blackFrame.length() > 0 && Shutter.cancelled == false && FFMPEG.error == false) 115 | { 116 | JOptionPane.showMessageDialog(frame, FFMPEG.blackFrame, Shutter.language.getProperty("functionBlackDetection"), JOptionPane.ERROR_MESSAGE); 117 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("saveResult"), Shutter.language.getProperty("analyzeEnded"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 118 | 119 | if (q == JOptionPane.YES_OPTION) 120 | { 121 | FileDialog dialog = new FileDialog(frame, Shutter.language.getProperty("saveResult"), FileDialog.SAVE); 122 | dialog.setDirectory(System.getProperty("user.home") + "/Desktop"); 123 | dialog.setVisible(true); 124 | 125 | if (dialog.getFile() != null) 126 | { 127 | try { 128 | PrintWriter writer = new PrintWriter(dialog.getDirectory() + dialog.getFile().replace(".txt", "") + ".txt", "UTF-8"); 129 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + fileName); 130 | writer.println(""); 131 | writer.println(FFMPEG.blackFrame); 132 | writer.close(); 133 | } catch (FileNotFoundException | UnsupportedEncodingException e) {} 134 | 135 | } 136 | 137 | } 138 | else 139 | { 140 | cancelled = false; 141 | } 142 | } 143 | else 144 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noErrorDetected"), Shutter.language.getProperty("functionBlackDetection"), JOptionPane.INFORMATION_MESSAGE); 145 | } 146 | 147 | private static boolean lastActions(File file, String fileName) { 148 | 149 | //Errors 150 | if (FFMPEG.error) 151 | { 152 | FFMPEG.errorList.append(fileName); 153 | FFMPEG.errorList.append(System.lineSeparator()); 154 | } 155 | 156 | //Process cancelled 157 | if (cancelled) 158 | { 159 | return true; 160 | } 161 | else 162 | { 163 | if(FFMPEG.error == false) 164 | FunctionUtils.completed++; 165 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 166 | } 167 | 168 | //Sending process 169 | FunctionUtils.addFileForMail(fileName); 170 | 171 | //Watch folder 172 | if (Shutter.scanIsRunning) 173 | { 174 | FunctionUtils.moveScannedFiles(file); 175 | BlackDetection.main(); 176 | return true; 177 | } 178 | return false; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/functions/Command.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.io.File; 23 | 24 | import application.Ftp; 25 | import application.Shutter; 26 | import library.EXIFTOOL; 27 | import library.FFMPEG; 28 | import settings.FunctionUtils; 29 | 30 | public class Command extends Shutter { 31 | 32 | public static void main() { 33 | 34 | Thread thread = new Thread(new Runnable(){ 35 | @Override 36 | public void run() { 37 | 38 | if (scanIsRunning == false) 39 | FunctionUtils.completed = 0; 40 | 41 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 42 | 43 | for (int i = 0 ; i < liste.getSize() ; i++) 44 | { 45 | //Render queue only accept selected files 46 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender"))) 47 | { 48 | boolean isSelected = false; 49 | 50 | for (String input : Shutter.fileList.getSelectedValuesList()) 51 | { 52 | if (liste.getElementAt(i).equals(input)) 53 | { 54 | isSelected = true; 55 | } 56 | } 57 | 58 | if (isSelected == false) 59 | { 60 | continue; 61 | } 62 | } 63 | 64 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 65 | 66 | if (file == null) 67 | break; 68 | 69 | try { 70 | 71 | String fileName = file.getName(); 72 | final String extension = fileName.substring(fileName.lastIndexOf(".")); 73 | 74 | lblCurrentEncoding.setText(fileName); 75 | 76 | //Output folder 77 | String labelOutput = FunctionUtils.setOutputDestination("", file); 78 | 79 | //File output name 80 | String prefix = ""; 81 | if (casePrefix.isSelected()) 82 | { 83 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false); 84 | } 85 | 86 | String extensionName = ""; 87 | if (btnExtension.isSelected()) 88 | { 89 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false); 90 | } 91 | 92 | //Output name 93 | String fileOutputName = labelOutput + "/" + prefix + fileName.replace(extension, extensionName + comboFilter.getEditor().getItem().toString()) ; 94 | 95 | //File output 96 | File fileOut = new File(fileOutputName); 97 | if(fileOut.exists()) 98 | { 99 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, "_", comboFilter.getEditor().getItem().toString()); 100 | 101 | if (fileOut == null) 102 | { 103 | cancelled = true; 104 | break; 105 | } 106 | else if (fileOut.toString().equals("skip")) 107 | { 108 | continue; 109 | } 110 | } 111 | 112 | //Command 113 | String cmd; 114 | if (comboFonctions.getEditor().getItem().toString().contains("-passlogfile")) //Passlogfile 115 | { 116 | String[] passlogfile = comboFonctions.getEditor().getItem().toString().substring(comboFonctions.getEditor().getItem().toString().indexOf("-passlogfile") + 13).split("\""); 117 | cmd = " " + comboFonctions.getEditor().getItem().toString().replace("ffmpeg", "").replace("-passlogfile " + '"' + passlogfile[1] + '"', "-passlogfile " + '"' + fileOut + '"') + " -y " ; 118 | } 119 | else 120 | cmd = " " + comboFonctions.getEditor().getItem().toString().replace("exiftool", "").replace("ffmpeg", ""); 121 | 122 | if (comboFonctions.getEditor().getItem().toString().contains("ffmpeg")) 123 | { 124 | cmd += " -y "; 125 | 126 | FFMPEG.run(" -i " + '"' + file.toString() + '"' + cmd + '"' + fileOut + '"'); 127 | 128 | do 129 | { 130 | Thread.sleep(100); 131 | } while(FFMPEG.runProcess.isAlive()); 132 | 133 | if (cmd.contains("-pass")) 134 | { 135 | FFMPEG.run(" -i " + '"' + file.toString() + '"' + cmd.replace("-pass 1", "-pass 2") + '"' + fileOut + '"'); 136 | } 137 | 138 | do 139 | { 140 | Thread.sleep(100); 141 | } while(FFMPEG.runProcess.isAlive()); 142 | } 143 | else if (comboFonctions.getEditor().getItem().toString().contains("exiftool")) 144 | { 145 | btnStart.setEnabled(false); 146 | 147 | EXIFTOOL.run(" -tagsfromfile " + '"' + file.toString() + '"' + cmd + " " + '"' + file.toString() + '"'); 148 | 149 | do 150 | { 151 | Thread.sleep(100); 152 | } while (EXIFTOOL.isRunning); 153 | 154 | btnStart.setEnabled(true); 155 | } 156 | 157 | //Removing temporary files 158 | final File folder = new File(fileOut.getParent()); 159 | FunctionUtils.listFilesForFolder(fileName.replace(extension, ""), folder); 160 | 161 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 162 | { 163 | if (lastActions(file, fileName, fileOut, labelOutput)) 164 | break; 165 | } 166 | 167 | } catch (InterruptedException e) { 168 | FFMPEG.error = true; 169 | } 170 | } 171 | 172 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 173 | enfOfFunction(); 174 | } 175 | 176 | }); 177 | thread.start(); 178 | 179 | } 180 | 181 | private static boolean lastActions(File file, String fileName, File fileOut, String output) { 182 | 183 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output)) 184 | return true; 185 | 186 | //Sending processes 187 | FunctionUtils.addFileForMail(fileName); 188 | Ftp.sendToFtp(fileOut); 189 | FunctionUtils.copyFile(fileOut); 190 | 191 | 192 | //Watch folder 193 | if (Shutter.scanIsRunning) 194 | { 195 | FunctionUtils.moveScannedFiles(file); 196 | Command.main(); 197 | return true; 198 | } 199 | return false; 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /src/functions/Conform.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.io.File; 23 | 24 | import application.Ftp; 25 | import application.Shutter; 26 | import application.Utils; 27 | import application.VideoPlayer; 28 | import library.FFMPEG; 29 | import library.FFPROBE; 30 | import settings.FunctionUtils; 31 | import settings.InputAndOutput; 32 | 33 | public class Conform extends Shutter { 34 | 35 | public static void main() { 36 | 37 | Thread thread = new Thread(new Runnable(){ 38 | @Override 39 | public void run() { 40 | 41 | if (scanIsRunning == false) 42 | FunctionUtils.completed = 0; 43 | 44 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 45 | 46 | for (int i = 0 ; i < liste.getSize() ; i++) 47 | { 48 | //Render queue only accept selected files 49 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender"))) 50 | { 51 | boolean isSelected = false; 52 | 53 | for (String input : Shutter.fileList.getSelectedValuesList()) 54 | { 55 | if (liste.getElementAt(i).equals(input)) 56 | { 57 | isSelected = true; 58 | } 59 | } 60 | 61 | if (isSelected == false) 62 | { 63 | continue; 64 | } 65 | } 66 | 67 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 68 | 69 | if (file == null) 70 | break; 71 | 72 | try { 73 | 74 | String fileName = file.getName(); 75 | String extension = fileName.substring(fileName.lastIndexOf(".")); 76 | 77 | lblCurrentEncoding.setText(fileName); 78 | 79 | //Data analyze 80 | if (FunctionUtils.analyze(file, false) == false) 81 | continue; 82 | 83 | //Output folder 84 | String labelOutput = FunctionUtils.setOutputDestination("", file); 85 | 86 | //File output name 87 | String prefix = ""; 88 | if (casePrefix.isSelected()) 89 | { 90 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false); 91 | } 92 | 93 | String extensionName = ""; 94 | if (btnExtension.isSelected()) 95 | { 96 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false); 97 | } 98 | 99 | //Output name 100 | String fileOutputName = labelOutput.replace("\\", "/") + "/" + prefix + fileName.replace(extension, extensionName + extension); 101 | 102 | //Audio 103 | String audio = setAudio(); 104 | 105 | //InOut 106 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 107 | 108 | //File output 109 | File fileOut = new File(fileOutputName); 110 | if (fileOut.exists()) 111 | { 112 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, extensionName + "_", extension); 113 | 114 | if (fileOut == null) 115 | { 116 | cancelled = true; 117 | break; 118 | } 119 | else if (fileOut.toString().equals("skip")) 120 | { 121 | continue; 122 | } 123 | } 124 | 125 | //Command 126 | float FPSOut = Float.parseFloat((comboFilter.getSelectedItem().toString().replace(" " + Shutter.language.getProperty("fps"), "").replace(",", "."))); 127 | float value = (float) (FFPROBE.currentFPS / FPSOut); 128 | 129 | String cmd = " -c:v copy -c:s copy" + audio + " -map v:0 -map a? -map s? -y "; 130 | FFMPEG.run(" -itsscale " + value + InputAndOutput.inPoint + " -i " + '"' + file + '"' + InputAndOutput.outPoint + cmd + '"' + fileOut + '"'); 131 | 132 | do 133 | { 134 | Thread.sleep(100); 135 | } 136 | while(FFMPEG.runProcess.isAlive()); 137 | 138 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 139 | { 140 | if (lastActions(file, fileName, fileOut, labelOutput)) 141 | break; 142 | } 143 | 144 | } catch (InterruptedException e) { 145 | FFMPEG.error = true; 146 | } 147 | } 148 | 149 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 150 | enfOfFunction(); 151 | } 152 | 153 | }); 154 | thread.start(); 155 | 156 | } 157 | 158 | private static String setAudio() { 159 | 160 | float AudioFPSIn = FFPROBE.currentFPS; 161 | float AudioFPSOut = Float.parseFloat((comboFilter.getSelectedItem().toString().replace(" " + Shutter.language.getProperty("fps"), "").replace(",", "."))); 162 | float value = (float) (AudioFPSOut / AudioFPSIn); 163 | if (value < 0.5f || value > 2.0f) 164 | return " -an"; 165 | else 166 | { 167 | if (FFPROBE.audioCodec != null && FFPROBE.audioCodec != "") 168 | return " -c:a " + FFPROBE.audioCodec + " -b:a " + FFPROBE.audioBitrate + "k -af atempo=" + value; 169 | else 170 | return " -an"; 171 | } 172 | 173 | } 174 | 175 | private static boolean lastActions(File file, String fileName, File fileOut, String output) { 176 | 177 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output)) 178 | return true; 179 | 180 | //Sending processes 181 | FunctionUtils.addFileForMail(fileName); 182 | Ftp.sendToFtp(fileOut); 183 | Utils.copyFile(fileOut); 184 | 185 | //Watch folder 186 | if (Shutter.scanIsRunning) 187 | { 188 | FunctionUtils.moveScannedFiles(file); 189 | Conform.main(); 190 | return true; 191 | } 192 | return false; 193 | } 194 | 195 | } -------------------------------------------------------------------------------- /src/functions/DVDRIP.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.io.File; 23 | import java.io.PrintWriter; 24 | 25 | import javax.swing.JOptionPane; 26 | 27 | import application.Console; 28 | import application.Ftp; 29 | import application.Shutter; 30 | import application.Utils; 31 | import library.FFMPEG; 32 | import library.FFPROBE; 33 | import settings.FunctionUtils; 34 | 35 | public class DVDRIP extends Shutter { 36 | 37 | public static void main() { 38 | 39 | Thread thread = new Thread(new Runnable(){ 40 | @Override 41 | public void run() { 42 | 43 | FunctionUtils.completed = 0; 44 | 45 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 46 | 47 | //Scan VIDEO_TS folder 48 | File [] volumes; 49 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 50 | volumes = new File("/Volumes").listFiles(); 51 | else 52 | volumes = File.listRoots(); 53 | 54 | //DVD folder 55 | File dvdFolder = setDVDFolder(volumes); 56 | 57 | if (dvdFolder == null) 58 | { 59 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noDVD"), Shutter.language.getProperty("DVDMissing"), JOptionPane.ERROR_MESSAGE); 60 | cancelled = true; 61 | } 62 | else 63 | { 64 | Console.consoleFFMPEG.append(System.lineSeparator() + dvdFolder + System.lineSeparator() ); 65 | 66 | //Récupération des fichiers vidéo .VOB 67 | String[] vobArray = new String[dvdFolder.listFiles().length]; 68 | int i = 0; 69 | for (File VOB : dvdFolder.listFiles()) 70 | { 71 | if (VOB.isHidden() == false) 72 | { 73 | String ext = VOB.toString().substring(VOB.toString().lastIndexOf(".")); 74 | 75 | if (VOB.getName().contains("VTS") && ext.equals(".VOB")) //Filtre des .VOB par VTS et extension 76 | { 77 | String [] s = VOB.getName().split("_"); 78 | if (s[2].replace(ext, "").equals("0") == false) 79 | { 80 | vobArray[i] = VOB.toString(); 81 | i ++; 82 | } 83 | } 84 | } 85 | } 86 | 87 | //Découpe des différentes vidéos 88 | File concatFile = new File(lblDestination1.getText() + "/DVD_RIP.txt"); 89 | 90 | if (concatFile.exists()) 91 | concatFile.delete(); 92 | 93 | //Création du fichier texte pour la liste 94 | PrintWriter writer = null; 95 | 96 | int vtsNumber = 1; 97 | String VOB = null; 98 | int dureeTotale = 0; 99 | for (i = 0; i < vobArray.length ; i++) 100 | { 101 | VOB = vobArray[i]; 102 | 103 | if (VOB != null) 104 | { 105 | String[] s = new File(VOB).getName().split("_"); 106 | int actualVOB = Integer.valueOf(s[1]); 107 | 108 | if (actualVOB == vtsNumber)//Par exemple si le VTS_01 contient VTS_01_00, VTS_01_02, VTS_01_03... on ajoute le fichier à la liste 109 | { 110 | if (concatFile.exists() == false) 111 | { 112 | try { 113 | writer = new PrintWriter(concatFile, "UTF-8"); 114 | } catch (Exception e1) {} 115 | } 116 | writer.println("file '" + VOB + "'"); 117 | 118 | FFPROBE.Data(VOB); 119 | do { 120 | try { 121 | Thread.sleep(100); 122 | } catch (InterruptedException e1) {} 123 | } while (FFPROBE.isRunning == true); 124 | dureeTotale += FFPROBE.totalLength; 125 | 126 | Console.consoleFFMPEG.append(VOB + System.lineSeparator()); 127 | } 128 | else //Si le fichier VTS passe de VTS_01 à VTS_02 on execute le bout à bout existant avant de le recréer ou si il n'y a pas de VTS_02 129 | { 130 | progressBar1.setMaximum((int) (dureeTotale / 1000)); 131 | 132 | //On enregistre le fichier de la liste des VOB 133 | writer.close(); 134 | 135 | if (runRIP(vtsNumber, concatFile, VOB)) 136 | break; 137 | 138 | //Après exécution on passe on VTS suivant et on scan le nombre de fichiers existant sous le même nom dans la condition if suivante 139 | vtsNumber = actualVOB; 140 | i--; 141 | dureeTotale = 0; 142 | } 143 | 144 | } 145 | } 146 | 147 | //On execute la dernière liste de VTS 148 | if (cancelled == false) 149 | { 150 | writer.close(); 151 | progressBar1.setMaximum((int) (dureeTotale / 1000)); 152 | runRIP(vtsNumber, concatFile, VOB); 153 | } 154 | 155 | } 156 | 157 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 158 | enfOfFunction(); 159 | } 160 | 161 | }); 162 | thread.start(); 163 | 164 | } 165 | 166 | protected static File setDVDFolder(File[] volumes) { 167 | 168 | for (File folder : volumes) 169 | { 170 | Console.consoleFFMPEG.append(String.valueOf(folder) + System.lineSeparator()); 171 | try{ 172 | for (File video_ts_folder : folder.listFiles()) 173 | { 174 | if (video_ts_folder.getName().equals("VIDEO_TS")) 175 | return video_ts_folder; 176 | } 177 | } catch (Exception e) {} 178 | } 179 | return null; 180 | } 181 | 182 | private static boolean runRIP(int vtsNumber, File concatFile, String VOB) { 183 | 184 | try { 185 | String videoName = "VIDEO_" + vtsNumber + ".VOB"; 186 | lblCurrentEncoding.setText(videoName); 187 | 188 | String labelOutput = lblDestination1.getText(); 189 | lblDestination1.setText(labelOutput); 190 | 191 | //File output 192 | File fileOut = new File(labelOutput + "/" + videoName); 193 | if(fileOut.exists()) 194 | { 195 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("eraseFile"), Shutter.language.getProperty("theFile") + " " + videoName + " " + Shutter.language.getProperty("alreadyExist"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 196 | if (q == JOptionPane.NO_OPTION) 197 | cancelled = true; 198 | } 199 | 200 | if (cancelled == false) 201 | { 202 | //Command 203 | String cmd = " -c:v copy -c:a copy -c:s copy -err_detect ignore_err -map v:0? -map a? -map s? -y "; 204 | FFMPEG.run(" -safe 0 -f concat -i " + '"' + concatFile.toString() + '"' + cmd + '"' + fileOut + '"'); 205 | 206 | do 207 | { 208 | Thread.sleep(100); 209 | } 210 | while(FFMPEG.runProcess.isAlive()); 211 | } 212 | else 213 | return true; 214 | 215 | if (cancelled == true) 216 | { 217 | lastActions(VOB, fileOut, labelOutput); 218 | concatFile.delete(); 219 | return true; 220 | } 221 | 222 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 223 | { 224 | lastActions(VOB, fileOut, labelOutput); 225 | } 226 | 227 | } catch (InterruptedException e) { 228 | FFMPEG.error = true; 229 | } 230 | finally { //Dans tous les cas on vide la liste de fichiers VOB 231 | concatFile.delete(); 232 | } 233 | return false; 234 | } 235 | 236 | private static void lastActions(String fileName, File fileOut, String output) { 237 | 238 | FunctionUtils.cleanFunction(null, fileName, fileOut, output); 239 | 240 | //Sending processes 241 | FunctionUtils.addFileForMail(fileName); 242 | Ftp.sendToFtp(fileOut); 243 | Utils.copyFile(fileOut); 244 | 245 | } 246 | } -------------------------------------------------------------------------------- /src/functions/FrameMD5.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.io.File; 23 | 24 | import application.Ftp; 25 | import application.Shutter; 26 | import application.Utils; 27 | import application.VideoPlayer; 28 | import library.FFMPEG; 29 | import settings.FunctionUtils; 30 | import settings.InputAndOutput; 31 | 32 | public class FrameMD5 extends Shutter { 33 | 34 | public static Thread thread; 35 | 36 | public static void main() { 37 | 38 | thread = new Thread(new Runnable() { 39 | 40 | @Override 41 | public void run() { 42 | 43 | if (scanIsRunning == false) 44 | FunctionUtils.completed = 0; 45 | 46 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 47 | 48 | for (int i = 0 ; i < liste.getSize() ; i++) 49 | { 50 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 51 | 52 | if (file == null) 53 | break; 54 | 55 | try { 56 | 57 | String fileName = file.getName(); 58 | String extension = fileName.substring(fileName.lastIndexOf(".")); 59 | String container = ".framemd5"; 60 | 61 | lblCurrentEncoding.setText(fileName); 62 | 63 | //Data analyze 64 | if (FunctionUtils.analyze(file, false) == false) 65 | continue; 66 | 67 | //InOut 68 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 69 | 70 | //Output folder 71 | String labelOutput = FunctionUtils.setOutputDestination("", file); 72 | 73 | //File output name 74 | String prefix = ""; 75 | if (casePrefix.isSelected()) 76 | { 77 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false); 78 | } 79 | 80 | String extensionName = ""; 81 | if (btnExtension.isSelected()) 82 | { 83 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false); 84 | } 85 | 86 | //Output name 87 | String fileOutputName = labelOutput.replace("\\", "/") + "/" + prefix + fileName.replace(extension, extensionName + container); 88 | 89 | //File output 90 | File fileOut = new File(fileOutputName); 91 | if (fileOut.exists()) 92 | { 93 | fileOut = FunctionUtils.fileReplacement(labelOutput, prefix + fileName, extension, extensionName + "_", container); 94 | 95 | if (fileOut == null) 96 | { 97 | cancelled = true; 98 | break; 99 | } 100 | else if (fileOut.toString().equals("skip")) 101 | { 102 | continue; 103 | } 104 | } 105 | 106 | //Concat mode or Image sequence 107 | String concat = FunctionUtils.setConcat(file, labelOutput); 108 | if ((grpImageSequence.isVisible() && caseEnableSequence.isSelected())) 109 | { 110 | file = new File(labelOutput.replace("\\", "/") + "/" + fileName.replace(extension, ".txt")); 111 | } 112 | 113 | //Command 114 | FFMPEG.run(InputAndOutput.inPoint + concat + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + " -f framemd5 -y " + '"' + fileOut + '"'); 115 | 116 | do { 117 | Thread.sleep(100); 118 | } while(FFMPEG.runProcess.isAlive()); 119 | 120 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false 121 | || FFMPEG.saveCode == false && caseEnableSequence.isSelected()) 122 | { 123 | if (lastActions(file, fileName, fileOut, labelOutput)) 124 | break; 125 | } 126 | 127 | } catch (InterruptedException e) { 128 | FFMPEG.error = true; 129 | } 130 | } 131 | 132 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 133 | enfOfFunction(); 134 | } 135 | 136 | }); 137 | thread.start(); 138 | 139 | } 140 | 141 | private static boolean lastActions(File file, String fileName, File fileOut, String output) { 142 | 143 | if (FunctionUtils.cleanFunction(file, fileName, fileOut, output)) 144 | return true; 145 | 146 | //Sending processes 147 | FunctionUtils.addFileForMail(fileName); 148 | Ftp.sendToFtp(fileOut); 149 | Utils.copyFile(fileOut); 150 | 151 | //Image sequence and merge 152 | if (caseEnableSequence.isSelected()) 153 | return true; 154 | 155 | //Watch folder 156 | if (Shutter.scanIsRunning) 157 | { 158 | FunctionUtils.moveScannedFiles(file); 159 | FrameMD5.main(); 160 | return true; 161 | } 162 | 163 | return false; 164 | } 165 | 166 | } -------------------------------------------------------------------------------- /src/functions/LoudnessTruePeak.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.io.File; 23 | import java.io.FileNotFoundException; 24 | import java.io.PrintWriter; 25 | import java.io.UnsupportedEncodingException; 26 | 27 | import javax.swing.JOptionPane; 28 | 29 | import application.Shutter; 30 | import application.VideoPlayer; 31 | import library.FFMPEG; 32 | import library.FFPROBE; 33 | import settings.FunctionUtils; 34 | import settings.InputAndOutput; 35 | 36 | public class LoudnessTruePeak extends Shutter { 37 | 38 | public static void main() { 39 | 40 | Thread thread = new Thread(new Runnable(){ 41 | @Override 42 | public void run() { 43 | 44 | if (scanIsRunning == false) 45 | FunctionUtils.completed = 0; 46 | 47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 48 | 49 | for (int i = 0 ; i < liste.getSize() ; i++) 50 | { 51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 52 | 53 | if (file == null) 54 | break; 55 | 56 | try { 57 | 58 | String fileName = file.getName(); 59 | lblCurrentEncoding.setText(fileName); 60 | 61 | //Data analyze 62 | if (FunctionUtils.analyze(file, false) == false) 63 | continue; 64 | 65 | //InOut 66 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 67 | 68 | //Audio 69 | String audio = setAudio(); 70 | 71 | //Sending command 72 | String cmd; 73 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 74 | cmd = " -vn" + audio + " -f null -"; 75 | else 76 | cmd = " -vn" + audio + " -f null -" + '"'; 77 | 78 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd); 79 | 80 | do 81 | { 82 | Thread.sleep(100); 83 | } 84 | while(FFMPEG.runProcess.isAlive()); 85 | 86 | //Show detection 87 | if (cancelled == false) 88 | showDetection(file); 89 | 90 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 91 | { 92 | if (lastActions(file, fileName)) 93 | break; 94 | } 95 | 96 | } catch (InterruptedException e) { 97 | FFMPEG.error = true; 98 | } 99 | } 100 | 101 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 102 | enfOfFunction(); 103 | } 104 | 105 | }); 106 | thread.start(); 107 | 108 | } 109 | 110 | private static String setAudio() { 111 | 112 | if (FFPROBE.stereo) 113 | { 114 | return " -af ebur128=peak=true"; 115 | } 116 | else if (FFPROBE.channels > 1) 117 | { 118 | if (FFPROBE.channels >= 4) 119 | { 120 | String[] options = {"A1 & A2", "A3 & A4"}; 121 | int q = JOptionPane.showOptionDialog(frame, language.getProperty("ChooseMultitrack"), language.getProperty("multitrack"), JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]); 122 | if (q == 0) 123 | return " -filter_complex " + '"' + "[0:a:0][0:a:1]amerge=inputs=2[a];[a]ebur128=peak=true" + '"'; 124 | else 125 | return " -filter_complex " + '"' + "[0:a:2][0:a:3]amerge=inputs=2[a];[a]ebur128=peak=true" + '"'; 126 | } 127 | else 128 | return " -filter_complex " + '"' + "[0:a:0][0:a:1]amerge=inputs=2[a];[a]ebur128=peak=true" + '"'; 129 | } 130 | else 131 | return " -af ebur128=peak=true"; 132 | } 133 | 134 | private static void showDetection(File file) { 135 | 136 | if (FFMPEG.analyseLufs != null && Shutter.cancelled == false && FFMPEG.error == false) 137 | { 138 | if (comboFilter.getSelectedIndex() == 0) // Display 139 | { 140 | JOptionPane.showMessageDialog(frame, FFMPEG.analyseLufs, file.getName(), JOptionPane.INFORMATION_MESSAGE); 141 | } 142 | else // Save 143 | { 144 | //File output name 145 | String prefix = ""; 146 | if (casePrefix.isSelected()) 147 | { 148 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false); 149 | } 150 | 151 | String extensionName = ""; 152 | if (btnExtension.isSelected()) 153 | { 154 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false); 155 | } 156 | 157 | //Output name 158 | String fileOutputName = FunctionUtils.setOutputDestination("", file).replace("\\", "/") + "/" + prefix + file.getName() + extensionName; 159 | 160 | try { 161 | PrintWriter writer = new PrintWriter(fileOutputName + ".txt", "UTF-8"); 162 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + file.getName()); 163 | writer.println(""); 164 | writer.println(FFMPEG.analyseLufs + System.lineSeparator() + System.lineSeparator() + FFMPEG.shortTermValues); 165 | writer.close(); 166 | } catch (FileNotFoundException | UnsupportedEncodingException e) {} 167 | } 168 | } 169 | } 170 | 171 | private static boolean lastActions(File file, String fileName) { 172 | 173 | //Errors 174 | if (FFMPEG.error) 175 | { 176 | FFMPEG.errorList.append(fileName); 177 | FFMPEG.errorList.append(System.lineSeparator()); 178 | } 179 | 180 | //Process cancelled 181 | if (cancelled) 182 | { 183 | return true; 184 | } 185 | else 186 | { 187 | if(FFMPEG.error == false) 188 | FunctionUtils.completed++; 189 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 190 | } 191 | 192 | //Sending process 193 | FunctionUtils.addFileForMail(fileName); 194 | 195 | //Watch folder 196 | if (Shutter.scanIsRunning) 197 | { 198 | FunctionUtils.moveScannedFiles(file); 199 | LoudnessTruePeak.main(); 200 | return true; 201 | } 202 | return false; 203 | } 204 | 205 | } -------------------------------------------------------------------------------- /src/functions/OfflineDetection.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.awt.FileDialog; 23 | import java.io.File; 24 | import java.io.FileNotFoundException; 25 | import java.io.PrintWriter; 26 | import java.io.UnsupportedEncodingException; 27 | 28 | import javax.swing.JOptionPane; 29 | 30 | import application.Shutter; 31 | import application.VideoPlayer; 32 | import library.FFMPEG; 33 | import settings.FunctionUtils; 34 | import settings.InputAndOutput; 35 | 36 | public class OfflineDetection extends Shutter { 37 | 38 | public static void main() { 39 | 40 | Thread thread = new Thread(new Runnable(){ 41 | @Override 42 | public void run() { 43 | 44 | if (scanIsRunning == false) 45 | FunctionUtils.completed = 0; 46 | 47 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 48 | 49 | for (int i = 0 ; i < liste.getSize() ; i++) 50 | { 51 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 52 | 53 | if (file == null) 54 | break; 55 | 56 | try { 57 | 58 | String fileName = file.getName(); 59 | lblCurrentEncoding.setText(fileName); 60 | 61 | //Data analyze 62 | if (FunctionUtils.analyze(file, false) == false) 63 | continue; 64 | 65 | //InOut 66 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 67 | 68 | //Stats_file 69 | String stats_file; 70 | if (System.getProperty("os.name").contains("Windows")) 71 | stats_file = "stats_file"; 72 | else 73 | stats_file = Shutter.dirTemp + "stats_file"; 74 | 75 | //Command 76 | String cmd = " -i " + '"' + Shutter.dirTemp + "offline.png" + '"' + " -lavfi " + '"' + "[0:v]scale=1920x1080[source];[1:v]scale=1920x1080[reference];[source][reference]psnr=" + stats_file + '"' + " -an -f null -"; 77 | 78 | if (System.getProperty("os.name").contains("Windows")) 79 | cmd += '"'; 80 | 81 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd); 82 | 83 | do 84 | { 85 | Thread.sleep(100); 86 | } 87 | while(FFMPEG.runProcess.isAlive()); 88 | 89 | //Show detection 90 | if (cancelled == false) 91 | showDetection(fileName); 92 | 93 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 94 | { 95 | if (lastActions(file, fileName)) 96 | break; 97 | } 98 | 99 | } catch (InterruptedException e) { 100 | FFMPEG.error = true; 101 | } 102 | } 103 | 104 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 105 | enfOfFunction(); 106 | } 107 | 108 | }); 109 | thread.start(); 110 | 111 | } 112 | 113 | private static void showDetection(String fileName) { 114 | 115 | if (FFMPEG.mediaOfflineFrame.length() > 0 && Shutter.cancelled == false && FFMPEG.error == false) 116 | { 117 | JOptionPane.showMessageDialog(frame, FFMPEG.mediaOfflineFrame, Shutter.language.getProperty("functionOfflineDetection"), JOptionPane.ERROR_MESSAGE); 118 | int q = JOptionPane.showConfirmDialog(Shutter.frame, Shutter.language.getProperty("saveResult"), Shutter.language.getProperty("analyzeEnded"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 119 | 120 | if (q == JOptionPane.YES_OPTION) 121 | { 122 | FileDialog dialog = new FileDialog(frame, Shutter.language.getProperty("saveResult"), FileDialog.SAVE); 123 | dialog.setDirectory(System.getProperty("user.home") + "/Desktop"); 124 | dialog.setVisible(true); 125 | 126 | if (dialog.getFile() != null) 127 | { 128 | try { 129 | PrintWriter writer = new PrintWriter(dialog.getDirectory() + dialog.getFile().replace(".txt", "") + ".txt", "UTF-8"); 130 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + fileName); 131 | writer.println(""); 132 | writer.println(FFMPEG.mediaOfflineFrame); 133 | writer.close(); 134 | } catch (FileNotFoundException | UnsupportedEncodingException e) {} 135 | 136 | } 137 | 138 | }//End Question 139 | else 140 | { 141 | cancelled = false; 142 | } 143 | } 144 | else 145 | JOptionPane.showMessageDialog(frame, Shutter.language.getProperty("noErrorDetected"), Shutter.language.getProperty("functionOfflineDetection"), JOptionPane.INFORMATION_MESSAGE); 146 | } 147 | 148 | private static boolean lastActions(File file, String fileName) { 149 | 150 | //Errors 151 | if (FFMPEG.error) 152 | { 153 | FFMPEG.errorList.append(fileName); 154 | FFMPEG.errorList.append(System.lineSeparator()); 155 | } 156 | 157 | //Process cancelled 158 | if (cancelled) 159 | { 160 | return true; 161 | } 162 | else 163 | { 164 | if(FFMPEG.error == false) 165 | FunctionUtils.completed++; 166 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 167 | } 168 | 169 | //Sending process 170 | FunctionUtils.addFileForMail(fileName); 171 | 172 | //Watch folder 173 | if (Shutter.scanIsRunning) 174 | { 175 | FunctionUtils.moveScannedFiles(file); 176 | OfflineDetection.main(); 177 | return true; 178 | } 179 | return false; 180 | } 181 | } -------------------------------------------------------------------------------- /src/functions/VMAF.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package functions; 21 | 22 | import java.awt.FileDialog; 23 | import java.io.File; 24 | import java.io.FileNotFoundException; 25 | import java.io.PrintWriter; 26 | import java.io.UnsupportedEncodingException; 27 | import javax.swing.JOptionPane; 28 | 29 | import application.Shutter; 30 | import application.VideoPlayer; 31 | import library.FFMPEG; 32 | import settings.FunctionUtils; 33 | import settings.InputAndOutput; 34 | 35 | public class VMAF extends Shutter { 36 | 37 | boolean warningSourceFile = true; 38 | 39 | public static void main() { 40 | 41 | Thread thread = new Thread(new Runnable(){ 42 | @Override 43 | public void run() { 44 | 45 | if (scanIsRunning == false) 46 | FunctionUtils.completed = 0; 47 | 48 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 49 | 50 | for (int i = 0 ; i < liste.getSize() ; i++) 51 | { 52 | File file = FunctionUtils.setInputFile(new File(liste.getElementAt(i))); 53 | 54 | if (file == null) 55 | break; 56 | 57 | JOptionPane.showMessageDialog(frame, language.getProperty("sourceFile") + language.getProperty("colon") + System.lineSeparator() + file.getName(), "VMAF", JOptionPane.INFORMATION_MESSAGE); 58 | 59 | FileDialog dialog = new FileDialog(frame, language.getProperty("source"), FileDialog.LOAD); 60 | dialog.setDirectory(new File(file.toString()).getParent()); 61 | dialog.setLocation(frame.getLocation().x - 50, frame.getLocation().y + 50); 62 | dialog.setAlwaysOnTop(true); 63 | dialog.setMultipleMode(false); 64 | dialog.setVisible(true); 65 | 66 | if (dialog.getFile() == null) 67 | { 68 | continue; 69 | } 70 | 71 | try { 72 | 73 | String fileName = file.getName(); 74 | lblCurrentEncoding.setText(fileName); 75 | 76 | //Data analyze 77 | if (FunctionUtils.analyze(file, false) == false) 78 | continue; 79 | 80 | //InOut 81 | InputAndOutput.getInputAndOutput(VideoPlayer.getFileList(file.toString())); 82 | 83 | //Sending command 84 | String cmd; 85 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 86 | cmd = " -filter_complex libvmaf -an -f null -"; 87 | else 88 | cmd = " -filter_complex libvmaf -an -f null -" + '"'; 89 | 90 | FFMPEG.run(InputAndOutput.inPoint + " -i " + '"' + file.toString() + '"' + InputAndOutput.inPoint + " -i " + '"' + dialog.getDirectory() + dialog.getFile().toString() + '"' + InputAndOutput.outPoint + cmd); 91 | 92 | do 93 | { 94 | Thread.sleep(100); 95 | } 96 | while(FFMPEG.runProcess.isAlive()); 97 | 98 | //Show detection 99 | if (cancelled == false) 100 | showDetection(file); 101 | 102 | if (FFMPEG.saveCode == false && btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 103 | { 104 | if (lastActions(file, fileName)) 105 | break; 106 | } 107 | 108 | } catch (InterruptedException e) { 109 | FFMPEG.error = true; 110 | } 111 | } 112 | 113 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) == false) 114 | enfOfFunction(); 115 | } 116 | 117 | }); 118 | thread.start(); 119 | 120 | } 121 | 122 | private static void showDetection(File file) { 123 | 124 | if (FFMPEG.VMAFScore != null && Shutter.cancelled == false && FFMPEG.error == false) 125 | { 126 | if (comboFilter.getSelectedIndex() == 0) // Display 127 | { 128 | JOptionPane.showMessageDialog(frame, file.getName() + System.lineSeparator() + FFMPEG.VMAFScore, "VMAF", JOptionPane.INFORMATION_MESSAGE); 129 | } 130 | else // Save 131 | { 132 | //File output name 133 | String prefix = ""; 134 | if (casePrefix.isSelected()) 135 | { 136 | prefix = FunctionUtils.setPrefixSuffix(txtPrefix.getText(), false); 137 | } 138 | 139 | String extensionName = ""; 140 | if (btnExtension.isSelected()) 141 | { 142 | extensionName = FunctionUtils.setPrefixSuffix(txtExtension.getText(), false); 143 | } 144 | 145 | //Output name 146 | String fileOutputName = FunctionUtils.setOutputDestination("", file).replace("\\", "/") + "/" + prefix + file.getName() + extensionName; 147 | 148 | try { 149 | PrintWriter writer = new PrintWriter(fileOutputName + ".txt", "UTF-8"); 150 | writer.println(Shutter.language.getProperty("analyzeOf") + " " + file.getName()); 151 | writer.println(""); 152 | writer.println(FFMPEG.VMAFScore); 153 | writer.close(); 154 | } catch (FileNotFoundException | UnsupportedEncodingException e) {} 155 | } 156 | } 157 | } 158 | 159 | private static boolean lastActions(File file, String fileName) { 160 | 161 | //Errors 162 | if (FFMPEG.error) 163 | { 164 | FFMPEG.errorList.append(fileName); 165 | FFMPEG.errorList.append(System.lineSeparator()); 166 | } 167 | 168 | //Process cancelled 169 | if (cancelled) 170 | { 171 | return true; 172 | } 173 | else 174 | { 175 | if(FFMPEG.error == false) 176 | FunctionUtils.completed++; 177 | lblFilesEnded.setText(FunctionUtils.completedFiles(FunctionUtils.completed)); 178 | } 179 | 180 | //Sending process 181 | FunctionUtils.addFileForMail(fileName); 182 | 183 | //Watch folder 184 | if (Shutter.scanIsRunning) 185 | { 186 | FunctionUtils.moveScannedFiles(file); 187 | VMAF.main(); 188 | return true; 189 | } 190 | return false; 191 | } 192 | 193 | } -------------------------------------------------------------------------------- /src/library/BMXTRANSWRAP.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.IOException; 24 | import java.io.InputStreamReader; 25 | import java.io.OutputStream; 26 | 27 | import application.Console; 28 | import application.RenderQueue; 29 | import application.Shutter; 30 | 31 | public class BMXTRANSWRAP extends Shutter { 32 | 33 | public static boolean error = false; 34 | public static boolean isRunning = false; 35 | public static Thread runProcess; 36 | public static Process process; 37 | 38 | public static void run(final String cmd) { 39 | 40 | Console.consoleBMXTRANSWRAP.append(Shutter.language.getProperty("command") + " " + cmd); 41 | 42 | error = false; 43 | 44 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled()) 45 | { 46 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "bmxtranswrap " + cmd, lblDestination1.getText()}); 47 | RenderQueue.caseRunParallel.setSelected(false); 48 | RenderQueue.caseRunParallel.setEnabled(false); 49 | RenderQueue.parallelValue.setEnabled(false); 50 | 51 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours")); 52 | 53 | if (caseChangeFolder1.isSelected() == false) 54 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource")); 55 | } 56 | else 57 | { 58 | disableAll(); 59 | 60 | progressBar1.setValue(0); 61 | progressBar1.setMaximum(100); 62 | 63 | runProcess = new Thread(new Runnable() { 64 | @Override 65 | public void run() { 66 | try { 67 | String PathToBMX; 68 | ProcessBuilder processBMX; 69 | if (System.getProperty("os.name").contains("Windows")) 70 | { 71 | PathToBMX = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 72 | PathToBMX = PathToBMX.substring(1,PathToBMX.length()-1); 73 | PathToBMX = '"' + PathToBMX.substring(0,(int) (PathToBMX.lastIndexOf("/"))).replace("%20", " ") + "/Library/bmxtranswrap.exe" + '"'; 74 | processBMX = new ProcessBuilder(PathToBMX + " " + cmd); 75 | } 76 | else 77 | { 78 | PathToBMX = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 79 | PathToBMX = PathToBMX.substring(0,PathToBMX.length()-1); 80 | PathToBMX = PathToBMX.substring(0,(int) (PathToBMX.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/bmxtranswrap"; 81 | processBMX = new ProcessBuilder("/bin/bash", "-c" , PathToBMX + " " + cmd); 82 | } 83 | 84 | isRunning = true; 85 | process = processBMX.start(); 86 | 87 | OutputStream out = process.getOutputStream(); 88 | out.write("os get /value".getBytes()); 89 | out.flush(); 90 | 91 | InputStreamReader isr = new InputStreamReader(process.getInputStream()); 92 | BufferedReader br = new BufferedReader(isr); 93 | String line; 94 | 95 | //Analyse des données 96 | do { 97 | line = br.readLine(); 98 | 99 | if (line != null) 100 | { 101 | if (line.contains("%")) 102 | { 103 | String s[] = line.split("\\."); 104 | int value = Integer.valueOf(s[0].replace(" ", "")); 105 | progressBar1.setValue(value); 106 | } 107 | } 108 | 109 | } while(line !=null); 110 | process.waitFor(); 111 | 112 | } catch (IOException | InterruptedException e) { 113 | error = true; 114 | } finally { 115 | isRunning = false; 116 | } 117 | 118 | } 119 | }); 120 | runProcess.start(); 121 | } 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/library/DVDAUTHOR.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.IOException; 24 | import java.io.InputStreamReader; 25 | 26 | import application.Console; 27 | import application.RenderQueue; 28 | import application.Shutter; 29 | 30 | public class DVDAUTHOR extends Shutter { 31 | 32 | public static boolean error = false; 33 | public static boolean isRunning = false; 34 | public static Thread runProcess; 35 | public static Process process; 36 | 37 | public static void run(final String cmd) { 38 | 39 | Console.consoleDVDAUTHOR.append(Shutter.language.getProperty("command") + " " + cmd); 40 | 41 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled()) 42 | { 43 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "dvdauthor " + cmd, lblDestination1.getText()}); 44 | RenderQueue.caseRunParallel.setSelected(false); 45 | RenderQueue.caseRunParallel.setEnabled(false); 46 | RenderQueue.parallelValue.setEnabled(false); 47 | 48 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours")); 49 | 50 | if (caseChangeFolder1.isSelected() == false) 51 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource")); 52 | } 53 | else 54 | { 55 | progressBar1.setValue(0); 56 | progressBar1.setMaximum(100); 57 | 58 | runProcess = new Thread(new Runnable() { 59 | @Override 60 | public void run() { 61 | try { 62 | String PathToDVDAUTHOR; 63 | ProcessBuilder processDVDAUTHOR; 64 | if (System.getProperty("os.name").contains("Windows")) 65 | { 66 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 67 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(1,PathToDVDAUTHOR.length()-1); 68 | PathToDVDAUTHOR = '"' + PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", " ") + "/Library/dvdauthor.exe" + '"'; 69 | processDVDAUTHOR = new ProcessBuilder(PathToDVDAUTHOR + " " + cmd); 70 | } 71 | else 72 | { 73 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 74 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,PathToDVDAUTHOR.length()-1); 75 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/dvdauthor"; 76 | processDVDAUTHOR = new ProcessBuilder("/bin/bash", "-c" , PathToDVDAUTHOR + " " + cmd); 77 | } 78 | 79 | isRunning = true; 80 | process = processDVDAUTHOR.start(); 81 | 82 | String line; 83 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getErrorStream())); 84 | 85 | Console.consoleDVDAUTHOR.append(System.lineSeparator()); 86 | 87 | while ((line = input.readLine()) != null) { 88 | 89 | Console.consoleDVDAUTHOR.append(line + System.lineSeparator()); 90 | 91 | if (line.contains("%")) 92 | { 93 | String s[] = line.split(" "); 94 | int value = Integer.valueOf(s[s.length-1].replace("%)", "")); 95 | progressBar1.setValue(value); 96 | } 97 | 98 | }//While 99 | process.waitFor(); 100 | 101 | Console.consoleDVDAUTHOR.append(System.lineSeparator()); 102 | 103 | } catch (IOException | InterruptedException e) { 104 | error = true; 105 | } finally { 106 | isRunning = false; 107 | } 108 | 109 | } 110 | }); 111 | runProcess.start(); 112 | } 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/library/EXIFTOOL.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.InputStreamReader; 24 | 25 | import application.Console; 26 | import application.Shutter; 27 | 28 | public class EXIFTOOL extends Shutter { 29 | 30 | public static boolean error = false; 31 | public static boolean isRunning = false; 32 | public static Thread runProcess; 33 | public static String exifDate; 34 | public static String exifHours; 35 | public static String creationDate; 36 | public static String creationHours; 37 | public static String exifWidth; 38 | public static String exifHeight; 39 | private static boolean scanOrientation = true; 40 | private static Boolean horizontal = true; 41 | 42 | public static void run(final String cmd) { 43 | 44 | error = false; 45 | scanOrientation = true; 46 | horizontal = true; 47 | exifDate = "0000:00:00"; 48 | exifHours = "00:00:00"; 49 | creationDate = "0000:00:00"; 50 | creationHours = "00:00:00"; 51 | exifWidth = ""; 52 | exifHeight = ""; 53 | 54 | if (cmd != '"' + "" + '"') 55 | { 56 | Console.consoleEXIFTOOL.append(System.lineSeparator()); 57 | Console.consoleEXIFTOOL.append(Shutter.language.getProperty("command") + " " + cmd); 58 | } 59 | 60 | //Watermark scaling 61 | FFPROBE.previousImageWidth = FFPROBE.imageWidth; 62 | 63 | runProcess = new Thread(new Runnable() { 64 | @Override 65 | public void run() { 66 | 67 | try { 68 | 69 | String PathToEXIFTOOL; 70 | ProcessBuilder processEXIFTOOL; 71 | if (System.getProperty("os.name").contains("Windows")) 72 | { 73 | PathToEXIFTOOL = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 74 | PathToEXIFTOOL = PathToEXIFTOOL.substring(1,PathToEXIFTOOL.length()-1); 75 | PathToEXIFTOOL = '"' + PathToEXIFTOOL.substring(0,(int) (PathToEXIFTOOL.lastIndexOf("/"))).replace("%20", " ") + "/Library/exiftool.exe" + '"'; 76 | processEXIFTOOL = new ProcessBuilder(PathToEXIFTOOL + " " + cmd); 77 | } 78 | else 79 | { 80 | PathToEXIFTOOL = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 81 | PathToEXIFTOOL = PathToEXIFTOOL.substring(0,PathToEXIFTOOL.length()-1); 82 | PathToEXIFTOOL = PathToEXIFTOOL.substring(0,(int) (PathToEXIFTOOL.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/exiftool"; 83 | processEXIFTOOL = new ProcessBuilder("/bin/bash", "-c" , PathToEXIFTOOL + " " + cmd); 84 | } 85 | 86 | isRunning = true; 87 | Process process = processEXIFTOOL.start(); 88 | 89 | InputStreamReader isr = new InputStreamReader(process.getInputStream()); 90 | BufferedReader br = new BufferedReader(isr); 91 | 92 | String line; 93 | 94 | if (cmd != '"' + "" + '"') 95 | { 96 | Console.consoleEXIFTOOL.append(System.lineSeparator()); 97 | } 98 | 99 | //Analyse des données 100 | while ((line = br.readLine()) != null) 101 | { 102 | Console.consoleEXIFTOOL.append(line + System.lineSeparator()); 103 | 104 | if (line.contains("Error")) 105 | { 106 | error = true; 107 | } 108 | 109 | if (line.contains("Date/Time Original")) 110 | { 111 | String l = line.substring(line.indexOf(":") + 2); 112 | String f[] = l.split(" "); 113 | exifDate = f[0]; //2018:04:06 114 | exifHours = f[1]; //12:30:00 115 | } 116 | 117 | if (line.contains("Create Date") && line.contains("+") == false) 118 | { 119 | String l = line.substring(line.indexOf(":") + 2); 120 | String f[] = l.split(" "); 121 | creationDate = f[0].toString(); //2018:04:06 122 | 123 | String time[] = f[1].split(":"); //12:30:00 124 | creationHours = time[0] + ":" + time[1] + ":" + time[2]; 125 | } 126 | 127 | if (line.contains("Image Width")) 128 | exifWidth = line.substring(line.indexOf(":") + 2); 129 | 130 | if (line.contains("Image Height")) 131 | exifHeight = line.substring(line.indexOf(":") + 2); 132 | 133 | if (line.contains("Orientation") && scanOrientation) 134 | { 135 | if (line.substring(line.indexOf(":") + 2).contains("Horizontal") == false && line.substring(line.indexOf(":") + 2).contains("Rotate 180") == false) 136 | { 137 | horizontal = false; 138 | } 139 | 140 | scanOrientation = false; 141 | } 142 | } 143 | process.waitFor(); 144 | 145 | //Si il n'y a pas d'exif on lit la date de création système 146 | if (exifDate == "" && exifHours == "") 147 | { 148 | exifDate = creationDate; 149 | exifHours = creationHours; 150 | } 151 | 152 | //On inject la résolution dans FFPROBE 153 | if (exifWidth != "" && exifHeight != "") 154 | { 155 | if (horizontal) 156 | { 157 | FFPROBE.imageResolution = exifWidth + "x" + exifHeight; 158 | FFPROBE.imageWidth = Integer.parseInt(exifWidth); 159 | FFPROBE.imageHeight = Integer.parseInt(exifHeight); 160 | } 161 | else 162 | { 163 | FFPROBE.imageResolution = exifHeight + "x" + exifWidth; 164 | FFPROBE.imageWidth = Integer.parseInt(exifHeight); 165 | FFPROBE.imageHeight = Integer.parseInt(exifWidth); 166 | } 167 | 168 | FFPROBE.imageRatio = (float) FFPROBE.imageWidth / FFPROBE.imageHeight; 169 | } 170 | 171 | } catch (Exception e) { 172 | error = true; 173 | } finally { 174 | isRunning = false; 175 | } 176 | 177 | } 178 | }); 179 | runProcess.start(); 180 | } 181 | } -------------------------------------------------------------------------------- /src/library/MEDIAINFO.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.awt.Color; 23 | import java.awt.Cursor; 24 | import java.io.BufferedReader; 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | 29 | import javax.swing.JLabel; 30 | import javax.swing.JScrollPane; 31 | 32 | import application.Console; 33 | import application.Informations; 34 | import application.Shutter; 35 | import application.Utils; 36 | 37 | public class MEDIAINFO extends Shutter { 38 | 39 | static int dureeTotale = 0; 40 | public static boolean error = false; 41 | public static boolean isRunning = false; 42 | public static Thread runProcess; 43 | 44 | public static void run(final String file, boolean showInformationsFrame) { 45 | 46 | error = false; 47 | 48 | Console.consoleMEDIAINFO.append(Shutter.language.getProperty("command") + " --Output=HTML " + '"' + file.toString() + '"'); 49 | 50 | runProcess = new Thread(new Runnable() { 51 | @Override 52 | public void run() { 53 | 54 | if (showInformationsFrame) 55 | Informations.frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 56 | 57 | try { 58 | 59 | String PathToMEDIAINFO; 60 | ProcessBuilder processMEDIAINFO; 61 | if (System.getProperty("os.name").contains("Windows")) 62 | { 63 | PathToMEDIAINFO = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 64 | PathToMEDIAINFO = PathToMEDIAINFO.substring(1,PathToMEDIAINFO.length()-1); 65 | PathToMEDIAINFO = '"' + PathToMEDIAINFO.substring(0,(int) (PathToMEDIAINFO.lastIndexOf("/"))).replace("%20", " ") + "/Library/MediaInfo.exe" + '"'; 66 | processMEDIAINFO = new ProcessBuilder(PathToMEDIAINFO + " --Output=HTML " + '"' + file.toString() + '"'); 67 | } 68 | else 69 | { 70 | PathToMEDIAINFO = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 71 | PathToMEDIAINFO = PathToMEDIAINFO.substring(0,PathToMEDIAINFO.length()-1); 72 | PathToMEDIAINFO = PathToMEDIAINFO.substring(0,(int) (PathToMEDIAINFO.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/mediainfo"; 73 | processMEDIAINFO = new ProcessBuilder("/bin/bash", "-c" , PathToMEDIAINFO + " --Output=HTML " + '"' + file.toString() + '"'); 74 | } 75 | 76 | isRunning = true; 77 | Process process = processMEDIAINFO.start(); 78 | 79 | InputStreamReader isr = new InputStreamReader(process.getInputStream()); 80 | BufferedReader br = new BufferedReader(isr); 81 | StringBuilder infoData = new StringBuilder(); 82 | 83 | Console.consoleMEDIAINFO.append(System.lineSeparator()); 84 | 85 | String line; 86 | while ((line = br.readLine()) != null) 87 | { 88 | infoData.append(line); 89 | /* 90 | //Variable Frame Rate 91 | if (line.contains("Frame rate mode :")) 92 | { 93 | infoData.append(System.lineSeparator()); 94 | 95 | line = br.readLine(); 96 | infoData.append(line); 97 | 98 | String s[] = line.split(">"); 99 | String s2[] = s[1].split("<"); 100 | 101 | if (s2[0].equals("Variable")) 102 | { 103 | FFPROBE.currentFPS = FFPROBE.timebaseFPS; 104 | } 105 | }*/ 106 | 107 | //Timecode 108 | if (line.contains("Time code of first frame") && FFPROBE.timecode1 == "") 109 | { 110 | infoData.append(System.lineSeparator()); 111 | 112 | line = br.readLine(); 113 | infoData.append(line); 114 | 115 | String s[] = line.split(">"); 116 | String s2[] = s[1].split("<"); 117 | String str[]= s2[0].replace(";" , ":").split(":"); 118 | 119 | FFPROBE.timecode1 = str[0]; 120 | FFPROBE.timecode2 = str[1]; 121 | FFPROBE.timecode3 = str[2]; 122 | FFPROBE.timecode4 = str[3]; 123 | } 124 | 125 | //Interlaced 126 | if (line.contains("Scan type :") && FFPROBE.interlaced == null) 127 | { 128 | infoData.append(System.lineSeparator()); 129 | 130 | line = br.readLine(); 131 | infoData.append(line); 132 | 133 | String s[] = line.split(">"); 134 | String s2[] = s[1].split("<"); 135 | 136 | if (s2[0].equals("Interlaced")) 137 | { 138 | FFPROBE.interlaced = "1"; 139 | } 140 | else 141 | FFPROBE.interlaced = "0"; 142 | } 143 | 144 | //Field order 145 | if (line.contains("Scan order :") && FFPROBE.interlaced.equals("1") && FFPROBE.fieldOrder == null) 146 | { 147 | infoData.append(System.lineSeparator()); 148 | 149 | line = br.readLine(); 150 | infoData.append(line); 151 | 152 | String s[] = line.split(">"); 153 | String s2[] = s[1].split("<"); 154 | 155 | if (s2[0].equals("Bottom Field First")) 156 | { 157 | FFPROBE.fieldOrder = "1"; 158 | } 159 | else 160 | FFPROBE.fieldOrder = "0"; 161 | } 162 | 163 | infoData.append(System.lineSeparator()); 164 | } 165 | 166 | process.waitFor(); 167 | 168 | Console.consoleMEDIAINFO.append(System.lineSeparator()); 169 | 170 | String StrTotal = ""; 171 | 172 | int x = infoData.indexOf(""); 173 | x = infoData.indexOf("", x + 1); 174 | x = infoData.indexOf("", x + 1); 175 | 176 | StrTotal = infoData.substring(infoData.indexOf("") + (x + 3)); 177 | 178 | Console.consoleMEDIAINFO.append("" + System.lineSeparator() + "" + System.lineSeparator() + StrTotal.toString()); 179 | 180 | if (showInformationsFrame) 181 | { 182 | //Adding tab 183 | Informations.addTabControl(); 184 | 185 | String informationsFrameSize = String.valueOf((int) Informations.frame.getSize().width - 320); 186 | String htmlSize = ""; 187 | for (String l : StrTotal.toString().split(System.lineSeparator())) 188 | { 189 | if (l.contains("td width")) 190 | { 191 | String s[] = l.split("\""); 192 | htmlSize = s[1]; 193 | } 194 | 195 | } 196 | 197 | JLabel content = new JLabel("" + System.lineSeparator() + "" + System.lineSeparator() 198 | + StrTotal.toString().replace(htmlSize, informationsFrameSize).replace("", "").replace("border:1px solid Navy", "border-bottom:1px solid rgb(55,55,55); border-top:1px solid rgb(55,55,55)")); 199 | 200 | content.setBackground(Utils.c30); 201 | content.setForeground(new Color(235,235,240)); 202 | content.setOpaque(true); 203 | 204 | JScrollPane scrollPane = new JScrollPane(); 205 | scrollPane.setViewportView(content); 206 | scrollPane.setBounds(Informations.tabPanel.getBounds()); 207 | scrollPane.getVerticalScrollBar().setUnitIncrement(16); 208 | 209 | Informations.lblWait.setVisible(false); 210 | Informations.lblArrows.setVisible(true); 211 | 212 | Informations.infoTabbedPane.addTab(new File(file).getName(), scrollPane); 213 | } 214 | 215 | } catch (IOException | InterruptedException e) { 216 | error = true; 217 | } finally { 218 | isRunning = false; 219 | } 220 | 221 | if (showInformationsFrame) 222 | Informations.frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 223 | } 224 | }); 225 | runProcess.start(); 226 | } 227 | 228 | } 229 | -------------------------------------------------------------------------------- /src/library/NCNN.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStreamReader; 26 | 27 | import javax.imageio.ImageIO; 28 | 29 | import application.Console; 30 | import application.RenderQueue; 31 | import application.Shutter; 32 | import application.VideoPlayer; 33 | 34 | public class NCNN extends Shutter { 35 | 36 | static int dureeTotale = 0; 37 | public static boolean error = false; 38 | public static boolean isRunning = false; 39 | public static Thread runProcess; 40 | public static Process process; 41 | public static String modelsPath; 42 | 43 | public static void run(final String cmd, boolean isVideoPlayer) { 44 | 45 | error = false; 46 | progressBar1.setValue(0); 47 | tempsEcoule.setVisible(false); 48 | 49 | Console.consoleNCNN.append(language.getProperty("command") + " " + cmd); 50 | 51 | if (btnStart.getText().equals(language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled() && cmd.contains("-f rawvideo") == false && cmd.contains("preview.bmp") == false && cmd.contains("preview.png") == false) 52 | { 53 | RenderQueue.tableRow.addRow(new Object[] { lblCurrentEncoding.getText(), "ncnn" + cmd, lblDestination1.getText()}); 54 | RenderQueue.caseRunParallel.setSelected(false); 55 | RenderQueue.caseRunParallel.setEnabled(false); 56 | RenderQueue.parallelValue.setEnabled(false); 57 | 58 | lblCurrentEncoding.setText(language.getProperty("lblEncodageEnCours")); 59 | 60 | if (caseChangeFolder1.isSelected() == false) 61 | lblDestination1.setText(language.getProperty("sameAsSource")); 62 | } 63 | else 64 | { 65 | isRunning = true; 66 | 67 | runProcess = new Thread(new Runnable() { 68 | 69 | @Override 70 | public void run() { 71 | 72 | try { 73 | 74 | String PathToNCNN; 75 | ProcessBuilder processNCNN; 76 | 77 | if (System.getProperty("os.name").contains("Windows")) 78 | { 79 | PathToNCNN = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 80 | PathToNCNN = PathToNCNN.substring(1,PathToNCNN.length()-1); 81 | PathToNCNN = '"' + PathToNCNN.substring(0,(int) (PathToNCNN.lastIndexOf("/"))).replace("%20", " ") + "/Library/realesrgan-ncnn-vulkan.exe" + '"'; 82 | processNCNN = new ProcessBuilder(PathToNCNN + cmd); 83 | } 84 | else 85 | { 86 | PathToNCNN = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 87 | PathToNCNN = PathToNCNN.substring(0,PathToNCNN.length()-1); 88 | PathToNCNN = PathToNCNN.substring(0,(int) (PathToNCNN.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/realesrgan-ncnn-vulkan"; 89 | processNCNN = new ProcessBuilder("/bin/bash", "-c" , PathToNCNN + cmd); 90 | } 91 | 92 | process = processNCNN.start(); 93 | 94 | String line; 95 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getErrorStream())); 96 | 97 | if (caseCreateSequence.isSelected() == false 98 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")))) 99 | { 100 | progressBar1.setValue(0); 101 | progressBar1.setMaximum(100); 102 | } 103 | 104 | Console.consoleNCNN.append(System.lineSeparator()); 105 | 106 | int progressValue = 0; 107 | 108 | if (isVideoPlayer == false) 109 | btnStart.setText(language.getProperty("btnPauseFunction")); 110 | 111 | while ((line = input.readLine()) != null) 112 | { 113 | if (line.contains("%") == false) 114 | { 115 | Console.consoleNCNN.append(line + System.lineSeparator()); 116 | } 117 | 118 | if ((line.contains("%") && caseCreateSequence.isSelected() == false 119 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")))) 120 | || line.contains("%") && isVideoPlayer) 121 | { 122 | String s[] = line.split("\\."); 123 | if (System.getProperty("os.name").contains("Windows")) 124 | { 125 | s = line.split(","); 126 | } 127 | 128 | progressBar1.setValue(Integer.parseInt(s[0])); 129 | } 130 | else if (line.contains("done")) 131 | { 132 | progressValue ++; 133 | progressBar1.setValue(progressValue); 134 | 135 | if (comboFonctions.getSelectedItem().toString().contains("JPEG") == false 136 | && comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")) == false 137 | && caseDisplay.isSelected()) 138 | { 139 | try { 140 | String s[] = line.split(" "); 141 | VideoPlayer.frameVideo = ImageIO.read(new File(s[2].toString())); 142 | VideoPlayer.player.repaint(); 143 | } catch (Exception e) {} 144 | } 145 | } 146 | } 147 | process.waitFor(); 148 | 149 | Console.consoleNCNN.append(System.lineSeparator()); 150 | 151 | } catch (IOException | InterruptedException e) { 152 | error = true; 153 | } finally { 154 | 155 | isRunning = false; 156 | 157 | if (caseCreateSequence.isSelected() == false 158 | && (comboFonctions.getSelectedItem().toString().contains("JPEG") || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")))) 159 | { 160 | if (cancelled == false) 161 | { 162 | progressBar1.setValue(100); 163 | } 164 | else 165 | progressBar1.setValue(0); 166 | } 167 | } 168 | 169 | } 170 | }); 171 | runProcess.start(); 172 | } 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/library/PDF.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.awt.Cursor; 23 | import java.awt.image.BufferedImage; 24 | import java.io.File; 25 | 26 | import org.apache.pdfbox.pdmodel.PDDocument; 27 | import org.apache.pdfbox.rendering.ImageType; 28 | import org.apache.pdfbox.rendering.PDFRenderer; 29 | 30 | import application.Shutter; 31 | import application.VideoPlayer; 32 | 33 | public class PDF extends Shutter { 34 | 35 | public static boolean error = false; 36 | public static boolean isRunning = false; 37 | public static Thread runProcess; 38 | public static int pagesCount = 1; 39 | 40 | public static void run(File file, int pageNumber) { 41 | 42 | error = false; 43 | progressBar1.setValue(0); 44 | btnStart.setEnabled(false); 45 | 46 | runProcess = new Thread(new Runnable() { 47 | 48 | @Override 49 | public void run() { 50 | 51 | try { 52 | 53 | isRunning = true; 54 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 55 | 56 | PDDocument document = PDDocument.load(file); 57 | PDFRenderer pdfRenderer = new PDFRenderer(document); 58 | 59 | pagesCount = document.getNumberOfPages(); 60 | 61 | VideoPlayer.preview = pdfRenderer.renderImageWithDPI(pageNumber, 300, ImageType.RGB); 62 | 63 | document.close(); 64 | 65 | FFPROBE.interlaced = null; 66 | FFPROBE.analyzedMedia = VideoPlayer.videoPath; 67 | 68 | VideoPlayer.setInfo(); 69 | 70 | } catch (Exception e) { 71 | error = true; 72 | } finally { 73 | btnStart.setEnabled(true); 74 | isRunning = false; 75 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 76 | } 77 | 78 | } 79 | }); 80 | runProcess.start(); 81 | 82 | } 83 | 84 | public static void info(String file) { 85 | 86 | error = false; 87 | 88 | FFPROBE.hasAudio = false; 89 | FFPROBE.totalLength = 0; 90 | 91 | //Watermark scaling 92 | FFPROBE.previousImageWidth = FFPROBE.imageWidth; 93 | 94 | runProcess = new Thread(new Runnable() { 95 | 96 | @Override 97 | public void run() { 98 | 99 | try { 100 | 101 | isRunning = true; 102 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 103 | 104 | PDDocument document = PDDocument.load(new File(file)); 105 | PDFRenderer pdfRenderer = new PDFRenderer(document); 106 | 107 | pagesCount = document.getNumberOfPages(); 108 | 109 | BufferedImage image = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB); 110 | 111 | FFPROBE.imageResolution = image.getWidth() + "x" + image.getHeight(); 112 | FFPROBE.imageWidth = image.getWidth(); 113 | FFPROBE.imageHeight = image.getHeight(); 114 | FFPROBE.imageRatio = (float) image.getWidth() / image.getHeight(); 115 | 116 | document.close(); 117 | 118 | } catch (Exception e) { 119 | error = true; 120 | } finally { 121 | isRunning = false; 122 | frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 123 | } 124 | 125 | } 126 | }); 127 | runProcess.start(); 128 | 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /src/library/SEVENZIP.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.awt.Desktop; 23 | import java.io.BufferedReader; 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.io.InputStreamReader; 27 | import java.io.OutputStream; 28 | 29 | import javax.swing.SwingUtilities; 30 | 31 | import application.Console; 32 | import application.Shutter; 33 | 34 | public class SEVENZIP extends Shutter { 35 | 36 | public static boolean isRunning = false; 37 | public static Thread runProcess; 38 | public static boolean error = false; 39 | 40 | public static void run(final String cmd, final boolean notUpdate){ 41 | 42 | runProcess = new Thread(new Runnable() { 43 | @Override 44 | public void run() { 45 | 46 | Console.consoleFFMPEG.append(Shutter.language.getProperty("command") + " " + cmd); 47 | 48 | try { 49 | String PathTo7za; 50 | ProcessBuilder process7za; 51 | if (System.getProperty("os.name").contains("Windows")) 52 | { 53 | PathTo7za = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 54 | PathTo7za = PathTo7za.substring(1,PathTo7za.length()-1); 55 | PathTo7za = '"' + PathTo7za.substring(0,(int) (PathTo7za.lastIndexOf("/"))).replace("%20", " ") + "/Library/7za.exe" + '"'; 56 | process7za = new ProcessBuilder(PathTo7za + " " + cmd); 57 | } 58 | else 59 | { 60 | PathTo7za = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 61 | PathTo7za = PathTo7za.substring(0,PathTo7za.length()-1); 62 | PathTo7za = PathTo7za.substring(0,(int) (PathTo7za.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/7za"; 63 | process7za = new ProcessBuilder("/bin/bash", "-c" , PathTo7za + " " + cmd); 64 | } 65 | 66 | isRunning = true; 67 | Process process = process7za.start(); 68 | 69 | OutputStream out = process.getOutputStream(); 70 | out.write("os get /value".getBytes()); 71 | out.flush(); 72 | 73 | InputStreamReader isr = new InputStreamReader(process.getInputStream()); 74 | BufferedReader br = new BufferedReader(isr); 75 | String line; 76 | 77 | Console.consoleFFMPEG.append(System.lineSeparator()); 78 | 79 | //Analyse des données 80 | do { 81 | line = br.readLine(); 82 | Console.consoleFFMPEG.append(line + System.lineSeparator()); 83 | } while (line != null); 84 | 85 | process.waitFor(); 86 | 87 | Console.consoleFFMPEG.append(System.lineSeparator()); 88 | 89 | isRunning = false; 90 | 91 | } catch (IOException | InterruptedException e) { 92 | System.out.println(cmd); 93 | error = true; 94 | } 95 | 96 | if (notUpdate) 97 | { 98 | if (error == false) 99 | { 100 | try { 101 | Desktop.getDesktop().open(new File(lblDestination1.getText())); 102 | } catch (IOException e1) {} 103 | } 104 | else 105 | FFMPEG.cancelled = true; 106 | 107 | SwingUtilities.invokeLater(new Runnable() 108 | { 109 | @Override 110 | public void run() { 111 | progressBar1.setIndeterminate(false); 112 | } 113 | }); 114 | 115 | FFMPEG.enfOfFunction(); 116 | FFMPEG.enableAll(); 117 | } 118 | 119 | } 120 | }); 121 | runProcess.start(); 122 | } 123 | 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /src/library/TSMUXER.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package library; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.IOException; 24 | import java.io.InputStreamReader; 25 | 26 | import application.Console; 27 | import application.RenderQueue; 28 | import application.Shutter; 29 | 30 | public class TSMUXER extends Shutter { 31 | 32 | static int dureeTotale = 0; 33 | public static boolean error = false; 34 | public static boolean isRunning = false; 35 | public static Thread runProcess; 36 | public static Process process; 37 | 38 | public static void run(final String cmd) { 39 | 40 | Console.consoleFFMPEG.append(System.lineSeparator()); 41 | Console.consoleTSMUXER.append(Shutter.language.getProperty("command") + " " + cmd); 42 | 43 | if (btnStart.getText().equals(Shutter.language.getProperty("btnAddToRender")) && RenderQueue.btnStartRender.isEnabled()) 44 | { 45 | RenderQueue.tableRow.addRow(new Object[] {lblCurrentEncoding.getText(), "tsMuxeR " + cmd, lblDestination1.getText()}); 46 | RenderQueue.caseRunParallel.setSelected(false); 47 | RenderQueue.caseRunParallel.setEnabled(false); 48 | RenderQueue.parallelValue.setEnabled(false); 49 | 50 | lblCurrentEncoding.setText(Shutter.language.getProperty("lblEncodageEnCours")); 51 | 52 | if (caseChangeFolder1.isSelected() == false) 53 | lblDestination1.setText(Shutter.language.getProperty("sameAsSource")); 54 | } 55 | else 56 | { 57 | progressBar1.setValue(0); 58 | progressBar1.setMaximum(100); 59 | 60 | runProcess = new Thread(new Runnable() { 61 | @Override 62 | public void run() { 63 | try { 64 | String PathToDVDAUTHOR; 65 | ProcessBuilder processDVDAUTHOR; 66 | if (System.getProperty("os.name").contains("Windows")) 67 | { 68 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 69 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(1,PathToDVDAUTHOR.length()-1); 70 | PathToDVDAUTHOR = '"' + PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", " ") + "/Library/tsMuxeR.exe" + '"'; 71 | processDVDAUTHOR = new ProcessBuilder(PathToDVDAUTHOR + " " + cmd); 72 | } 73 | else 74 | { 75 | PathToDVDAUTHOR = Shutter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 76 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,PathToDVDAUTHOR.length()-1); 77 | PathToDVDAUTHOR = PathToDVDAUTHOR.substring(0,(int) (PathToDVDAUTHOR.lastIndexOf("/"))).replace("%20", "\\ ") + "/Library/tsMuxeR"; 78 | processDVDAUTHOR = new ProcessBuilder("/bin/bash", "-c" , PathToDVDAUTHOR + " " + cmd); 79 | } 80 | 81 | isRunning = true; 82 | process = processDVDAUTHOR.start(); 83 | 84 | InputStreamReader isr = new InputStreamReader(process.getInputStream()); 85 | BufferedReader br = new BufferedReader(isr); 86 | 87 | Console.consoleTSMUXER.append(System.lineSeparator()); 88 | 89 | String line; 90 | do { 91 | line = br.readLine(); 92 | 93 | Console.consoleTSMUXER.append(line + System.lineSeparator()); 94 | 95 | if (line != null) 96 | { 97 | if (line.contains("%")) 98 | { 99 | String s[] = line.split("\\."); 100 | int value = Integer.parseInt(s[0]); 101 | progressBar1.setValue(value); 102 | } 103 | } 104 | 105 | } while (line != null); 106 | process.waitFor(); 107 | 108 | Console.consoleTSMUXER.append(System.lineSeparator()); 109 | 110 | } catch (IOException | InterruptedException e) { 111 | error = true; 112 | } finally { 113 | isRunning = false; 114 | } 115 | 116 | } 117 | }); 118 | runProcess.start(); 119 | } 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/settings/BitratesAdjustement.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import application.Shutter; 23 | import library.FFPROBE; 24 | 25 | public class BitratesAdjustement extends Shutter { 26 | 27 | public static boolean DVD2Pass; 28 | public static int DVDBitrate; 29 | 30 | public static String setPass(String outputFile) { 31 | 32 | if (case2pass.isSelected() || comboFonctions.getSelectedItem().toString().equals("DVD") && DVDBitrate <= 6000) 33 | { 34 | DVD2Pass = true; 35 | return " -pass 1 -passlogfile " + '"' + outputFile + '"'; 36 | } 37 | else 38 | DVD2Pass = false; 39 | 40 | return ""; 41 | } 42 | 43 | public static String setCrop(String filterComplex) { 44 | 45 | if (Shutter.caseEnableCrop.isSelected()) 46 | { 47 | if (filterComplex != "") 48 | filterComplex += "[w];[w]"; 49 | 50 | //IMPORTANT 51 | float imageRatio = 1.0f; 52 | 53 | int ow = FFPROBE.imageWidth; 54 | 55 | if (Shutter.comboFonctions.getSelectedItem().toString().equals("DVD") == false && Shutter.comboResolution.getSelectedItem().toString().equals(Shutter.language.getProperty("source")) == false) 56 | { 57 | if (comboResolution.getSelectedItem().toString().contains("AI")) 58 | { 59 | if (Shutter.comboResolution.getSelectedItem().toString().contains("2x")) 60 | { 61 | ow = (int) Math.round(ow * 2); 62 | } 63 | else 64 | { 65 | ow = (int) Math.round(ow * 4); 66 | } 67 | } 68 | else 69 | { 70 | String s[] = comboResolution.getSelectedItem().toString().split("x"); 71 | ow = Integer.parseInt(s[0]); 72 | } 73 | 74 | imageRatio = (float) FFPROBE.imageWidth / ow; 75 | } 76 | 77 | int cropWidth = Math.round((float) Integer.parseInt(Shutter.textCropWidth.getText()) / imageRatio); 78 | int cropHeight = Math.round((float) Integer.parseInt(Shutter.textCropHeight.getText()) / imageRatio); 79 | int cropX = Math.round((float)Integer.parseInt(Shutter.textCropPosX.getText()) / imageRatio); 80 | int cropY = Math.round((float)Integer.parseInt(Shutter.textCropPosY.getText()) / imageRatio); 81 | 82 | filterComplex += "crop=" + cropWidth + ":" + cropHeight + ":" + cropX + ":" + cropY; 83 | } 84 | 85 | return filterComplex; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/settings/Corrections.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import java.io.File; 23 | 24 | import application.Shutter; 25 | import library.FFMPEG; 26 | import library.FFPROBE; 27 | 28 | public class Corrections extends Shutter { 29 | 30 | public static File vidstab = null; 31 | 32 | public static String setStabilisation(String filterComplex, File file, String fichier, String concat) throws InterruptedException { 33 | 34 | if (Shutter.caseStabilisation.isSelected()) 35 | { 36 | if (System.getProperty("os.name").contains("Windows")) 37 | vidstab = new File("vidstab.trf"); 38 | else 39 | { 40 | 41 | vidstab = new File(Shutter.dirTemp + "vidstab.trf"); 42 | } 43 | 44 | lblCurrentEncoding.setText(Shutter.language.getProperty("analyzeOf") + " " + fichier); 45 | 46 | //Analyse du fichier 47 | String cmd; 48 | if (System.getProperty("os.name").contains("Mac") || System.getProperty("os.name").contains("Linux")) 49 | cmd = " -an -pix_fmt yuv420p -f yuv4mpegpipe - | PathToFFMPEG -i pipe:0 -vf vidstabdetect=result=" + vidstab.toString() + " -y -f null -"; 50 | else 51 | cmd = " -an -pix_fmt yuv420p -f yuv4mpegpipe - | PathToFFMPEG -i pipe:0 -vf vidstabdetect=result=" + vidstab.toString() + " -y -f null -" + '"'; 52 | 53 | FFMPEG.run(InputAndOutput.inPoint + concat + " -i " + '"' + file.toString() + '"' + InputAndOutput.outPoint + cmd); 54 | 55 | do 56 | { 57 | Thread.sleep(100); 58 | } 59 | while(FFMPEG.runProcess.isAlive()); 60 | 61 | if (filterComplex != "") filterComplex += ","; 62 | 63 | filterComplex += "vidstabtransform=input=" + vidstab.toString(); 64 | 65 | lblCurrentEncoding.setText(fichier); 66 | } 67 | 68 | return filterComplex; 69 | } 70 | 71 | public static String setDeflicker(String filterComplex) { 72 | 73 | if (Shutter.caseDeflicker.isSelected()) 74 | { 75 | if (filterComplex != "") filterComplex += ","; 76 | 77 | filterComplex += "split[a][b];[b]setpts=PTS-STARTPTS+" + (1 / FFPROBE.currentFPS) + "/TB,format=rgba,colorchannelmixer=aa=0.5[deflicker];[a][deflicker]overlay=shortest=1"; 78 | } 79 | 80 | return filterComplex; 81 | } 82 | 83 | public static String setDeband(String filterComplex) { 84 | 85 | if (Shutter.caseBanding.isSelected()) 86 | { 87 | if (filterComplex != "") filterComplex += ","; 88 | 89 | filterComplex += "deband=r=32"; 90 | } 91 | 92 | return filterComplex; 93 | } 94 | 95 | public static String setLimiter(String filterComplex) { 96 | 97 | if (Shutter.caseLimiter.isSelected()) 98 | { 99 | if (filterComplex != "") filterComplex += ","; 100 | 101 | if (FFPROBE.imageDepth == 8) 102 | filterComplex += "limiter=16:235"; 103 | else if (FFPROBE.imageDepth == 10) 104 | filterComplex += "limiter=64:940"; 105 | else if (FFPROBE.imageDepth == 12) 106 | filterComplex += "limiter=256:3760"; 107 | else if (FFPROBE.imageDepth == 16) 108 | filterComplex += "limiter=4096:60160"; 109 | } 110 | 111 | return filterComplex; 112 | } 113 | 114 | public static String setDetails(String filterComplex) { 115 | 116 | if (Shutter.caseDetails.isSelected()) 117 | { 118 | float value = (0 - (float) Shutter.sliderDetails.getValue() / 10); 119 | 120 | if (filterComplex != "") filterComplex += ","; 121 | 122 | filterComplex += "smartblur=1.0:" + value; 123 | } 124 | 125 | return filterComplex; 126 | } 127 | 128 | public static String setDenoiser(String filterComplex) { 129 | 130 | if (Shutter.caseDenoise.isSelected()) 131 | { 132 | int value = Shutter.sliderDenoise.getValue(); 133 | 134 | if (filterComplex != "") filterComplex += ","; 135 | 136 | filterComplex += "hqdn3d=" + value + ":" + value + ":" + value + ":" + value; 137 | } 138 | 139 | return filterComplex; 140 | } 141 | 142 | public static String setSmoothExposure(String filterComplex) { 143 | 144 | if (Shutter.caseSmoothExposure.isSelected()) 145 | { 146 | int value = Shutter.sliderSmoothExposure.getValue(); 147 | 148 | if (filterComplex != "") filterComplex += ","; 149 | 150 | filterComplex += "deflicker=s=" + Math.ceil((128 * value) / 100 + 1); 151 | } 152 | 153 | return filterComplex; 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /src/settings/Filter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import java.io.File; 23 | 24 | import application.Shutter; 25 | import library.EXIFTOOL; 26 | 27 | public class Filter extends Shutter { 28 | 29 | public static boolean dateFilter(File file) throws InterruptedException { 30 | 31 | if (caseYear.isSelected() || caseMonth.isSelected() || caseDay.isSelected() || caseFrom.isSelected()) 32 | { 33 | String date[] = EXIFTOOL.exifDate.split(":"); 34 | 35 | if (caseYear.isSelected()) 36 | { 37 | if (comboYear.getSelectedItem().toString().equals(date[0]) == false) 38 | return false; 39 | } 40 | if (caseMonth.isSelected()) 41 | { 42 | if (comboMonth.getSelectedItem().toString().equals(date[1]) == false) 43 | return false; 44 | } 45 | if (caseDay.isSelected()) 46 | { 47 | if (comboDay.getSelectedItem().toString().equals(date[2]) == false) 48 | return false; 49 | } 50 | if (caseFrom.isSelected()) 51 | { 52 | String exif[] = EXIFTOOL.exifHours.split(":"); 53 | String from[] = comboFrom.getSelectedItem().toString().split(":"); 54 | String to[] = comboTo.getSelectedItem().toString().split(":"); 55 | 56 | int eH = Integer.parseInt(exif[0]) * 60; 57 | int eM = Integer.parseInt(exif[1]); 58 | int exifTime = eH + eM; 59 | 60 | int fH = Integer.parseInt(from[0]) * 60; 61 | int fM = Integer.parseInt(from[1]); 62 | int fromTime = fH + fM; 63 | 64 | int tH = Integer.parseInt(to[0]) * 60; 65 | int tM = Integer.parseInt(to[1]); 66 | int toTime = tH + tM; 67 | 68 | if ((exifTime >= fromTime && exifTime <= toTime) == false) 69 | return false; 70 | } 71 | } 72 | return true; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/settings/ImageSequence.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import application.Shutter; 23 | import application.VideoPlayer; 24 | 25 | public class ImageSequence extends Shutter { 26 | 27 | public static String setBlend(String filterComplex) { 28 | 29 | if ((grpImageSequence.isVisible() || VideoPlayer.fullscreenPlayer) && caseBlend.isSelected()) 30 | { 31 | int value = sliderBlend.getValue(); 32 | StringBuilder blend = new StringBuilder(); 33 | for (int i = 0 ; i < value ; i++) 34 | { 35 | blend.append("tblend=all_mode=average,"); 36 | } 37 | 38 | blend.append("setpts=" + (float) 25 / Float.parseFloat(caseSequenceFPS.getSelectedItem().toString().replace(",", ".")) + "*PTS"); 39 | 40 | if (filterComplex != "") filterComplex += ","; 41 | 42 | filterComplex += blend; 43 | } 44 | 45 | return filterComplex; 46 | } 47 | 48 | public static String setMotionBlur(String filterComplex) { 49 | 50 | if ((grpImageSequence.isVisible() || VideoPlayer.fullscreenPlayer) && caseMotionBlur.isSelected()) 51 | { 52 | float fps = Float.parseFloat(caseSequenceFPS.getSelectedItem().toString().replace(",", ".")) * 2; 53 | 54 | if (filterComplex != "") filterComplex += ","; 55 | 56 | filterComplex += "minterpolate=fps=" + fps + ",tblend=all_mode=average,framestep=2"; 57 | } 58 | 59 | return filterComplex; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/settings/InputAndOutput.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import application.Shutter; 23 | import application.VideoPlayer; 24 | import library.FFPROBE; 25 | 26 | public class InputAndOutput extends Shutter { 27 | 28 | public static String inPoint = ""; 29 | public static String outPoint = ""; 30 | 31 | public static void getInputAndOutput(boolean setInputAndOutput) { 32 | 33 | if (setInputAndOutput) 34 | { 35 | float timeIn = (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60 + Integer.parseInt(VideoPlayer.caseInS.getText())) * FFPROBE.currentFPS + Integer.parseInt(VideoPlayer.caseInF.getText()); 36 | 37 | //NTSC timecode 38 | timeIn = Timecode.getNonDropFrameTC(timeIn); 39 | 40 | if (timeIn > 0.0f) 41 | { 42 | inPoint = " -ss " + (long) (timeIn * VideoPlayer.inputFramerateMS) + "ms"; 43 | } 44 | else 45 | inPoint = ""; 46 | 47 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2 && caseEnableSequence.isSelected() == false) 48 | { 49 | String frames[] = VideoPlayer.lblDuration.getText().split(" "); 50 | 51 | if ((comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionPicture")) || comboFonctions.getSelectedItem().toString().contains("JPEG")) && caseCreateSequence.isSelected()) 52 | { 53 | float outputFPS = FFPROBE.currentFPS / Float.parseFloat(comboInterpret.getSelectedItem().toString().replace(",", ".")); 54 | 55 | outPoint = " -frames:v " + (int) Math.ceil(Integer.parseInt(frames[frames.length - 2]) / outputFPS); 56 | } 57 | else if (FFPROBE.audioOnly || (caseConform.isSelected() && comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySpeed")) == false) 58 | || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionCut")) 59 | || comboFonctions.getSelectedItem().toString().equals(language.getProperty("functionRewrap")) 60 | || comboFonctions.getSelectedItem().toString().equals("VP8") 61 | || comboFonctions.getSelectedItem().toString().equals("VP9") 62 | || comboFonctions.getSelectedItem().toString().contains("XDCAM") 63 | || comboFonctions.getSelectedItem().toString().equals("AVC-Intra 100") 64 | || comboFonctions.getSelectedItem().toString().equals("XAVC")) //Issue for audio, libvpx & added mute track 65 | { 66 | outPoint = " -t " + (int) Math.floor(Integer.parseInt(frames[frames.length - 2]) * ((float) 1000 / FFPROBE.currentFPS)) + "ms"; 67 | } 68 | else 69 | { 70 | outPoint = " -frames:v " + Integer.parseInt(frames[frames.length - 2]); 71 | } 72 | } 73 | else 74 | outPoint = ""; 75 | 76 | if (VideoPlayer.comboMode.getSelectedItem().toString().equals(language.getProperty("splitMode"))) 77 | { 78 | outPoint += " -f segment -reset_timestamps 1 -segment_time " + VideoPlayer.splitValue.getText(); 79 | } 80 | } 81 | else 82 | { 83 | inPoint = ""; 84 | outPoint = ""; 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/settings/Timecode.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.nio.file.Files; 25 | import java.nio.file.Paths; 26 | import java.nio.file.attribute.BasicFileAttributes; 27 | import java.time.Instant; 28 | import java.time.ZoneId; 29 | import java.time.format.DateTimeFormatter; 30 | 31 | import application.Shutter; 32 | import application.VideoPlayer; 33 | import library.FFPROBE; 34 | 35 | public class Timecode extends Shutter { 36 | 37 | public static String setTimecode(File file) { 38 | 39 | String dropFrame = ":"; 40 | if (isDropFrame()) 41 | { 42 | dropFrame = ";"; 43 | } 44 | 45 | if (Shutter.caseConform.isSelected()) 46 | { 47 | if (Shutter.comboFPS.getSelectedItem().toString().equals("29,97") || Shutter.comboFPS.getSelectedItem().toString().equals("59,94")) 48 | { 49 | dropFrame = ";"; 50 | } 51 | else 52 | dropFrame = ":"; 53 | } 54 | 55 | if (caseGenerateFromDate.isSelected()) 56 | { 57 | try { 58 | 59 | BasicFileAttributes attrs = Files.readAttributes(Paths.get(file.toString()), BasicFileAttributes.class); 60 | Instant creationTime = attrs.creationTime().toInstant(); 61 | String date = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault()).format(creationTime); 62 | 63 | String s[] = date.split(":"); 64 | 65 | return " -timecode " + '"' + s[0] + ":" + s[1] + ":" + s[2] + dropFrame + "00" + '"'; 66 | 67 | } catch (IOException e) {} 68 | } 69 | else if (caseSetTimecode.isSelected()) 70 | { 71 | return " -timecode " + '"' + TCset1.getText() + ":" + TCset2.getText() + ":" + TCset3.getText() + dropFrame + TCset4.getText() + '"'; 72 | } 73 | else if (FFPROBE.timecode1 != "") 74 | { 75 | return " -timecode " + '"' + FFPROBE.timecode1 + ":" + FFPROBE.timecode2 + ":" + FFPROBE.timecode3 + dropFrame + FFPROBE.timecode4 + '"'; 76 | } 77 | 78 | return ""; 79 | } 80 | 81 | public static boolean isDropFrame() { 82 | 83 | if (FFPROBE.dropFrameTC.equals(":") == false && (FFPROBE.currentFPS == 29.97f || FFPROBE.currentFPS == 59.94f)) 84 | { 85 | return true; 86 | } 87 | else 88 | return false; 89 | } 90 | 91 | public static boolean isNonDropFrame() { 92 | 93 | if (FFPROBE.dropFrameTC.equals(":") && (FFPROBE.currentFPS == 29.97f || FFPROBE.currentFPS == 59.94f) || FFPROBE.currentFPS == 23.98f) 94 | { 95 | return true; 96 | } 97 | else 98 | return false; 99 | } 100 | 101 | public static float setNonDropFrameTC(float currentFrame) { 102 | 103 | //NTSC framerates && non drop frame timecode => remove a frame to reach round framerate 104 | if (isNonDropFrame() && currentFrame > 0) 105 | { 106 | float currentTime = VideoPlayer.playerCurrentFrame * VideoPlayer.inputFramerateMS; 107 | 108 | if (FFPROBE.currentFPS == 23.98f) 109 | { 110 | currentFrame -= (currentTime * 0.024 / 1000) - 1; 111 | } 112 | if (FFPROBE.currentFPS == 29.97f) 113 | { 114 | currentFrame -= (currentTime * 0.03 / 1000) - 1; 115 | } 116 | else if (FFPROBE.currentFPS == 59.94f) 117 | { 118 | currentFrame -= (currentTime * 0.06 / 1000) - 1; 119 | } 120 | } 121 | 122 | return currentFrame; 123 | } 124 | 125 | public static float getNonDropFrameTC(float currentFrame) { 126 | 127 | //Allows to set the current seeking values 128 | if (isNonDropFrame()) 129 | { 130 | float currentTime = currentFrame * VideoPlayer.inputFramerateMS; 131 | 132 | if (FFPROBE.currentFPS == 23.98f) 133 | { 134 | currentFrame += (currentTime * 0.024 / 1000); 135 | } 136 | else if (FFPROBE.currentFPS == 29.97f) 137 | { 138 | currentFrame += (currentTime * 0.03 / 1000); 139 | } 140 | else if (FFPROBE.currentFPS == 59.94f) 141 | { 142 | currentFrame += (currentTime * 0.06 / 1000); 143 | } 144 | 145 | return (float) Math.floor(currentFrame); 146 | } 147 | 148 | return currentFrame; 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /src/settings/Transitions.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * Copyright (C) 2025 PACIFICO PAUL 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program; if not, write to the Free Software Foundation, Inc., 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | * 18 | ********************************************************************************************/ 19 | 20 | package settings; 21 | 22 | import application.Shutter; 23 | import application.Settings; 24 | import application.VideoPlayer; 25 | import library.FFPROBE; 26 | 27 | public class Transitions extends Shutter { 28 | 29 | public static String setVideoFade(String filterComplex, boolean isVideoPlayer) { 30 | 31 | if (grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer) 32 | { 33 | //Fade-in 34 | if (Shutter.caseVideoFadeIn.isSelected()) 35 | { 36 | if (filterComplex != "") filterComplex += ","; 37 | 38 | long videoInValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeIn.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 39 | 40 | String color = "black"; 41 | if (Shutter.lblFadeInColor.getText().equals(language.getProperty("white"))) 42 | color = "white"; 43 | 44 | String videoFade = "fade=in:st=0ms:d=" + videoInValue + "ms:color=" + color; 45 | 46 | if (isVideoPlayer) 47 | { 48 | if (VideoPlayer.cursorWaveform.getX() == VideoPlayer.playerInMark || VideoPlayer.playTransition) 49 | { 50 | filterComplex += videoFade; 51 | } 52 | else 53 | filterComplex += "null"; 54 | } 55 | else 56 | filterComplex += videoFade; 57 | } 58 | 59 | //Fade-out 60 | if (Shutter.caseVideoFadeOut.isSelected()) 61 | { 62 | if (filterComplex != "") filterComplex += ","; 63 | 64 | long videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 65 | long videoStart = (long) FFPROBE.totalLength - videoOutValue; 66 | 67 | if (caseEnableSequence.isSelected()) 68 | { 69 | videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / Integer.parseInt(caseSequenceFPS.getSelectedItem().toString().replace(",", ".")))); 70 | videoStart = (long) ((float) ((float) 1000 / Integer.parseInt(caseSequenceFPS.getSelectedItem().toString().replace(",", "."))) * liste.getSize()) - videoOutValue; 71 | } 72 | else if (Settings.btnSetBab.isSelected()) 73 | { 74 | videoOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 75 | videoStart = (long) FunctionUtils.mergeDuration - videoOutValue; 76 | } 77 | else 78 | { 79 | long totalIn = (long) (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseInS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseInF.getText()) * (1000 / FFPROBE.currentFPS)); 80 | long totalOut = FFPROBE.totalLength; 81 | 82 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2) 83 | { 84 | totalOut = (long) (Integer.parseInt(VideoPlayer.caseOutH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseOutM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseOutS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseOutF.getText()) * (1000 / FFPROBE.currentFPS)); 85 | } 86 | 87 | if (isVideoPlayer) 88 | { 89 | totalIn = (long) Math.floor(VideoPlayer.playerCurrentFrame * ((float) 1000 / FFPROBE.currentFPS)); 90 | } 91 | 92 | if (VideoPlayer.comboMode.getSelectedItem().toString().contentEquals(Shutter.language.getProperty("cutUpper"))) 93 | { 94 | videoStart = (totalOut - totalIn) - videoOutValue; 95 | } 96 | else //Remove mode 97 | videoStart = FFPROBE.totalLength - (totalOut - totalIn) - videoOutValue; 98 | } 99 | 100 | String color = "black"; 101 | if (Shutter.lblFadeOutColor.getText().equals(language.getProperty("white"))) 102 | color = "white"; 103 | 104 | String videoFade = "fade=out:st=" + videoStart + "ms:d=" + videoOutValue + "ms:color=" + color; 105 | 106 | if (videoStart > 0) 107 | { 108 | filterComplex += videoFade; 109 | } 110 | else 111 | filterComplex += "null"; 112 | } 113 | } 114 | 115 | return filterComplex; 116 | } 117 | 118 | public static String setAudioFadeIn(boolean isVideoPlayer) { 119 | 120 | String audioFilter = ""; 121 | 122 | //Fade-in 123 | if ((grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer) && Shutter.caseAudioFadeIn.isSelected()) 124 | { 125 | long audioInValue = (long) (Integer.parseInt(Shutter.spinnerAudioFadeIn.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 126 | 127 | if (isVideoPlayer) 128 | { 129 | if (VideoPlayer.cursorWaveform.getX() == VideoPlayer.playerInMark || VideoPlayer.playTransition) 130 | { 131 | audioFilter += "afade=in:st=0ms:d=" + audioInValue + "ms"; 132 | } 133 | else 134 | audioFilter += "anull"; 135 | } 136 | else 137 | audioFilter += "afade=in:st=0ms:d=" + audioInValue + "ms"; 138 | } 139 | 140 | return audioFilter; 141 | } 142 | 143 | public static String setAudioFadeOut(boolean isVideoPlayer) { 144 | 145 | String audioFilter = ""; 146 | 147 | //Fade-out 148 | if ((grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer) && Shutter.caseAudioFadeOut.isSelected()) 149 | { 150 | long audioOutValue = (long) (Integer.parseInt(Shutter.spinnerAudioFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 151 | long audioStart = (long) FFPROBE.totalLength - audioOutValue; 152 | 153 | if (Settings.btnSetBab.isSelected()) 154 | { 155 | audioOutValue = (long) (Integer.parseInt(Shutter.spinnerVideoFadeOut.getText()) * ((float) 1000 / FFPROBE.currentFPS)); 156 | audioStart = (long) FunctionUtils.mergeDuration - audioOutValue; 157 | } 158 | else 159 | { 160 | long totalIn = (long) (Integer.parseInt(VideoPlayer.caseInH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseInM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseInS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseInF.getText()) * (1000 / FFPROBE.currentFPS)); 161 | long totalOut = FFPROBE.totalLength; 162 | 163 | if (VideoPlayer.playerOutMark < VideoPlayer.waveformContainer.getWidth() - 2) 164 | { 165 | totalOut = (long) (Integer.parseInt(VideoPlayer.caseOutH.getText()) * 3600000 + Integer.parseInt(VideoPlayer.caseOutM.getText()) * 60000 + Integer.parseInt(VideoPlayer.caseOutS.getText()) * 1000 + Integer.parseInt(VideoPlayer.caseOutF.getText()) * (1000 / FFPROBE.currentFPS)); 166 | } 167 | 168 | if (isVideoPlayer) 169 | { 170 | totalIn = (long) Math.floor(VideoPlayer.playerCurrentFrame * ((float) 1000 / FFPROBE.currentFPS)); 171 | } 172 | 173 | if (VideoPlayer.comboMode.getSelectedItem().toString().contentEquals(Shutter.language.getProperty("cutUpper"))) 174 | { 175 | audioStart = (totalOut - totalIn) - audioOutValue; 176 | } 177 | else //Remove mode 178 | audioStart = FFPROBE.totalLength - (totalOut - totalIn) - audioOutValue; 179 | } 180 | 181 | if (audioStart > 0) 182 | { 183 | audioFilter += "afade=out:st=" + audioStart + "ms:d=" + audioOutValue + "ms"; 184 | } 185 | else 186 | audioFilter += "anull"; 187 | } 188 | 189 | return audioFilter; 190 | } 191 | 192 | public static String setAudioSpeed() { 193 | 194 | String audioFilter = ""; 195 | 196 | if (grpTransitions.isEnabled() || VideoPlayer.fullscreenPlayer || grpAudio.isVisible() || grpSetAudio.isVisible()) 197 | { 198 | //Audio Speed 199 | if (caseConform.isSelected() && (comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySpeed")) 200 | || comboConform.getSelectedItem().toString().equals(language.getProperty("conformByReverse"))) 201 | || grpImageSequence.isVisible() && caseEnableSequence.isSelected()) 202 | { 203 | float newFPS = Float.parseFloat((comboFPS.getSelectedItem().toString()).replace(",", ".")); 204 | 205 | if (caseEnableSequence.isSelected()) 206 | { 207 | newFPS = Float.parseFloat((caseSequenceFPS.getSelectedItem().toString()).replace(",", ".")); 208 | } 209 | 210 | float value = (float) (newFPS / FFPROBE.currentFPS); 211 | 212 | if (value >= 0.5f && value <= 2.0f) 213 | { 214 | audioFilter = "atempo=" + value; 215 | } 216 | else if (value <= 0.5f && value >= 0.25f) 217 | { 218 | audioFilter = "atempo=" + ((float) value * 2); 219 | audioFilter += ","; 220 | audioFilter += "atempo=" + ((float) value * 2); 221 | } 222 | else if (value >= 2.0f && value <= 4.0f) 223 | { 224 | audioFilter = "atempo=" + ((float) value / 2); 225 | audioFilter += ","; 226 | audioFilter += "atempo=" + ((float) value / 2); 227 | } 228 | else 229 | { 230 | return " -an"; 231 | } 232 | } 233 | else if (caseConform.isSelected() && comboConform.getSelectedItem().toString().equals(language.getProperty("conformBySlowMotion"))) 234 | { 235 | return " -an"; 236 | } 237 | else if (caseConvertAudioFramerate.isSelected()) 238 | { 239 | float AudioFPSIn = Float.parseFloat((comboAudioIn.getSelectedItem().toString()).replace(",", ".")); 240 | float AudioFPSOut = Float.parseFloat((comboAudioOut.getSelectedItem().toString()).replace(",", ".")); 241 | float value = (float) (AudioFPSOut / AudioFPSIn); 242 | 243 | audioFilter += "atempo=" + value; 244 | } 245 | } 246 | 247 | return audioFilter; 248 | } 249 | 250 | } 251 | --------------------------------------------------------------------------------