diff --git a/ffmpeg4discord/__main__.py b/ffmpeg4discord/__main__.py index a5ff5d1..6fc56a1 100644 --- a/ffmpeg4discord/__main__.py +++ b/ffmpeg4discord/__main__.py @@ -73,12 +73,14 @@ def twopass_loop( break print( - dedent( - f"""\033[31m + "\033[31m" + + dedent( + f""" The output file size ({round(result.output_filesize, 2)}MB) is still above the target of {target_filesize}MB. Restarting... - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) Path(result.output_filename).unlink() @@ -433,12 +435,14 @@ def main() -> None: if version_info.update_available: print( - dedent( - f"""\033[33m + "\033[33m" + + dedent( + f""" Update available: {version_info.latest_version} (you are running {version_info.current_version}). Upgrade with: pip install -U ffmpeg4discord - \033[0m""" + """ ).strip() + + "\033[0m" ) # get args from the command line diff --git a/ffmpeg4discord/arguments.py b/ffmpeg4discord/arguments.py index 962dbbf..01715ed 100644 --- a/ffmpeg4discord/arguments.py +++ b/ffmpeg4discord/arguments.py @@ -283,14 +283,16 @@ def _parse_astreams(args: dict) -> dict: parsed = [int(p) for p in parts] except ValueError: logging.error( - dedent( - """\033[31m + "\033[31m" + + dedent( + """ Invalid --astreams format. Provide a comma-separated list of integers, e.g. --astreams "0,1,2". Ignoring --astreams. - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) args["astreams"] = None return args diff --git a/ffmpeg4discord/twopass.py b/ffmpeg4discord/twopass.py index 51a2784..c84d06b 100644 --- a/ffmpeg4discord/twopass.py +++ b/ffmpeg4discord/twopass.py @@ -192,8 +192,9 @@ def run_pass(ffoutput, pass_name: str, hint: str = "", **run_kwargs): # compile() can contain Path objects, so stringify each argument before joining. command = " ".join(str(arg) for arg in ffoutput.compile()) raise RuntimeError( - dedent( - f"""\033[31m + "\033[31m" + + dedent( + f""" FFmpeg failed during the {pass_name} pass. Look for FFmpeg's error message printed above this traceback -- it names the actual @@ -201,9 +202,10 @@ def run_pass(ffoutput, pass_name: str, hint: str = "", **run_kwargs): The command that failed was: {command} - \033[0m""" - ) - + (f"\033[31m{hint}\033[0m\n" if hint else "") + """ + ).strip() + + (f"\n\n{hint}" if hint else "") + + "\033[0m" ) from exc @@ -368,12 +370,14 @@ def _check_hdr(self): self.tonemap = tonemap_filters(self.probe) if not self.tonemap: logging.warning( - dedent( - """\033[31m + "\033[31m" + + dedent( + """ This video is HDR, but your ffmpeg can't convert it to SDR. It needs ffmpeg 8.0 or newer, or a build with zscale (libzimg). The output may look washed out. - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) def clip_times(self, settings: EncodeSettings) -> tuple[float, float]: @@ -394,17 +398,19 @@ def clip_times(self, settings: EncodeSettings) -> tuple[float, float]: if end <= start: raise ValueError( - dedent( - f"""\033[31m + "\033[31m" + + dedent( + f""" Time Paradox? Something is wrong with your clipping times. Use this information to further diagnose the problem: - - Your video is {self.duration / 60} minutes long + - Your video is {seconds_to_timestamp(self.duration)} long - Your clipping times are {seconds_to_timestamp(start)} to {seconds_to_timestamp(end)} - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) return start, end @@ -472,12 +478,14 @@ def _generate_params(self, settings: EncodeSettings, bitrate_targets: dict) -> d params["pass2"]["r"] = settings.framerate else: logging.warning( - dedent( - f"""\033[31m + "\033[31m" + + dedent( + f""" Desired framerate ({settings.framerate}) is more than original framerate ({self.init_framerate}). Keeping the original framerate... - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) # add in configurations specific to the codec @@ -603,12 +611,14 @@ def _output_filename(self, settings: EncodeSettings) -> str: if output.suffix != ext: logging.warning( - dedent( - f"""\033[31m + "\033[31m" + + dedent( + f""" You specified {settings.codec}, but your output file name ends with {output.suffix}. I've corrected this. - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) output = output.with_suffix(ext) @@ -636,12 +646,14 @@ def _apply_video_filters(self, video, settings: EncodeSettings): if ratio != outputratio: logging.warning( - dedent( - """\033[31m + "\033[31m" + + dedent( + """ Your output resolution's aspect ratio does not match the - input resolution's or your croped resolution's aspect ratio. - \033[0m""" - ) + input resolution's or your cropped resolution's aspect ratio. + """ + ).strip() + + "\033[0m" ) # Tone map last, so a smaller --resolution means fewer pixels to process. diff --git a/ffmpeg4discord/windows.py b/ffmpeg4discord/windows.py index dd422cc..21b3ce0 100644 --- a/ffmpeg4discord/windows.py +++ b/ffmpeg4discord/windows.py @@ -23,8 +23,9 @@ if platform.system() != "Windows": logging.warning( - dedent( - """\033[31m + "\033[31m" + + dedent( + """ THIS SCRIPT IS INTENDED FOR WINDOWS USERS If you are running this script on macOS, consider installing ffmpeg with @@ -32,8 +33,9 @@ If you are running this script on some Linux, learn more about your options to install ffmpeg on its website: https://ffmpeg.org/download.html#build-linux - \033[0m""" - ) + """ + ).strip() + + "\033[0m" ) sys.exit() diff --git a/tests/test_twopass.py b/tests/test_twopass.py index 8e32027..c5b445e 100644 --- a/tests/test_twopass.py +++ b/tests/test_twopass.py @@ -187,6 +187,14 @@ def test_end_not_after_start_raises(make_twopass, start, end): make_twopass().clip_times(make_settings(start=start, end=end)) +def test_end_not_after_start_message_has_no_indentation(make_twopass): + with pytest.raises(ValueError) as excinfo: + make_twopass().clip_times(make_settings(start="00:00:20", end="00:00:10")) + message = str(excinfo.value) + assert not any(line.startswith(" ") for line in message.splitlines()) + assert "Your video is 00:02:00 long" in message # the test video is 120 seconds + + def test_target_larger_than_input_raises(make_twopass): # the fake input is 53,000,000 bytes, about 50.5 MiB with pytest.raises(ValueError, match="larger than the input file"): @@ -704,8 +712,10 @@ def test_run_pass_adds_hint_to_error(): ffoutput = MagicMock() ffoutput.run.side_effect = ffmpeg.Error("ffmpeg", b"", b"") ffoutput.compile.return_value = ["ffmpeg"] - with pytest.raises(RuntimeError, match="try x264"): + with pytest.raises(RuntimeError) as excinfo: run_pass(ffoutput, "single", hint="try x264") + # the hint gets its own paragraph, inside the red text + assert str(excinfo.value).endswith("\n\ntry x264\033[0m") # --- HDR tone mapping (issue #77) ---