diff --git a/client/ayon_core/plugins/publish/extract_otio_review.py b/client/ayon_core/plugins/publish/extract_otio_review.py index 7a9a020ff0..f217be551c 100644 --- a/client/ayon_core/plugins/publish/extract_otio_review.py +++ b/client/ayon_core/plugins/publish/extract_otio_review.py @@ -54,7 +54,7 @@ class ExtractOTIOReview( # plugin default attributes to_width = 1280 to_height = 720 - output_ext = ".jpg" + output_ext = ".png" def process(self, instance): # Not all hosts can import these modules. @@ -510,6 +510,12 @@ class ExtractOTIOReview( "-tune", "stillimage" ]) + if video or sequence: + command.extend([ + "-vf", f"scale={self.to_width}:{self.to_height}:flags=lanczos", + "-compression_level", "5", + ]) + # add output attributes command.extend([ "-start_number", str(out_frame_start) @@ -520,9 +526,10 @@ class ExtractOTIOReview( input_extension and self.output_ext == input_extension ): - command.extend([ - "-c", "copy" - ]) + command.extend(["-c", "copy"]) + else: + # For lossy formats, force re-encode + command.extend(["-pix_fmt", "rgba"]) # add output path at the end command.append(output_path) diff --git a/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py b/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py index 45191a2c53..6a74df7f43 100644 --- a/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py +++ b/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py @@ -103,17 +103,18 @@ def test_image_sequence_with_embedded_tc_and_handles_out_of_range(): # 10 head black handles generated from gap (991-1000) "/path/to/ffmpeg -t 0.4166666666666667 -r 24.0 -f lavfi -i " "color=c=black:s=1280x720 -tune stillimage -start_number 991 " - "C:/result/output.%04d.jpg", + "-pix_fmt rgba C:/result/output.%04d.png", # 10 tail black handles generated from gap (1102-1111) "/path/to/ffmpeg -t 0.4166666666666667 -r 24.0 -f lavfi -i " "color=c=black:s=1280x720 -tune stillimage -start_number 1102 " - "C:/result/output.%04d.jpg", + "-pix_fmt rgba C:/result/output.%04d.png", # Report from source exr (1001-1101) with enforce framerate "/path/to/ffmpeg -start_number 1000 -framerate 24.0 -i " - f"C:\\exr_embedded_tc{os.sep}output.%04d.exr -start_number 1001 " - "C:/result/output.%04d.jpg" + f"C:\\exr_embedded_tc{os.sep}output.%04d.exr " + "-vf scale=1280:720:flags=lanczos -compression_level 5 " + "-start_number 1001 -pix_fmt rgba C:/result/output.%04d.png" ] assert calls == expected @@ -130,20 +131,23 @@ def test_image_sequence_and_handles_out_of_range(): expected = [ # 5 head black frames generated from gap (991-995) - "/path/to/ffmpeg -t 0.2 -r 25.0 -f lavfi -i color=c=black:s=1280x720" - " -tune stillimage -start_number 991 C:/result/output.%04d.jpg", + "/path/to/ffmpeg -t 0.2 -r 25.0 -f lavfi -i color=c=black:s=1280x720 " + "-tune stillimage -start_number 991 -pix_fmt rgba " + "C:/result/output.%04d.png", # 9 tail back frames generated from gap (1097-1105) - "/path/to/ffmpeg -t 0.36 -r 25.0 -f lavfi -i color=c=black:s=1280x720" - " -tune stillimage -start_number 1097 C:/result/output.%04d.jpg", + "/path/to/ffmpeg -t 0.36 -r 25.0 -f lavfi -i color=c=black:s=1280x720 " + "-tune stillimage -start_number 1097 -pix_fmt rgba " + "C:/result/output.%04d.png", # Report from source tiff (996-1096) # 996-1000 = additional 5 head frames # 1001-1095 = source range conformed to 25fps # 1096-1096 = additional 1 tail frames "/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i " - f"C:\\tif_seq{os.sep}output.%04d.tif -start_number 996" - f" C:/result/output.%04d.jpg" + f"C:\\tif_seq{os.sep}output.%04d.tif " + "-vf scale=1280:720:flags=lanczos -compression_level 5 " + "-start_number 996 -pix_fmt rgba C:/result/output.%04d.png" ] assert calls == expected @@ -163,8 +167,9 @@ def test_movie_with_embedded_tc_no_gap_handles(): # - first_frame = 14 src - 10 (head tail) = frame 4 = 0.1666s # - duration = 68fr (source) + 20fr (handles) = 88frames = 3.666s "/path/to/ffmpeg -ss 0.16666666666666666 -t 3.6666666666666665 " - "-i C:\\data\\qt_embedded_tc.mov -start_number 991 " - "C:/result/output.%04d.jpg" + "-i C:\\data\\qt_embedded_tc.mov -vf scale=1280:720:flags=lanczos " + "-compression_level 5 -start_number 991 -pix_fmt rgba " + "C:/result/output.%04d.png" ] assert calls == expected @@ -181,12 +186,14 @@ def test_short_movie_head_gap_handles(): expected = [ # 10 head black frames generated from gap (991-1000) "/path/to/ffmpeg -t 0.4 -r 25.0 -f lavfi -i color=c=black:s=1280x720" - " -tune stillimage -start_number 991 C:/result/output.%04d.jpg", + " -tune stillimage -start_number 991 -pix_fmt rgba " + "C:/result/output.%04d.png", # source range + 10 tail frames # duration = 50fr (source) + 10fr (tail handle) = 60 fr = 2.4s - "/path/to/ffmpeg -ss 0.0 -t 2.4 -i C:\\data\\movie.mp4" - " -start_number 1001 C:/result/output.%04d.jpg" + "/path/to/ffmpeg -ss 0.0 -t 2.4 -i C:\\data\\movie.mp4 -vf " + "scale=1280:720:flags=lanczos -compression_level 5 " + "-start_number 1001 -pix_fmt rgba C:/result/output.%04d.png" ] assert calls == expected @@ -204,13 +211,14 @@ def test_short_movie_tail_gap_handles(): # 10 tail black frames generated from gap (1067-1076) "/path/to/ffmpeg -t 0.4166666666666667 -r 24.0 -f lavfi -i " "color=c=black:s=1280x720 -tune stillimage -start_number 1067 " - "C:/result/output.%04d.jpg", + "-pix_fmt rgba C:/result/output.%04d.png", # 10 head frames + source range # duration = 10fr (head handle) + 66fr (source) = 76fr = 3.16s "/path/to/ffmpeg -ss 1.0416666666666667 -t 3.1666666666666665 -i " - "C:\\data\\qt_no_tc_24fps.mov -start_number 991" - " C:/result/output.%04d.jpg" + "C:\\data\\qt_no_tc_24fps.mov -vf scale=1280:720:flags=lanczos " + "-compression_level 5 -start_number 991 -pix_fmt rgba " + "C:/result/output.%04d.png" ] assert calls == expected @@ -239,62 +247,75 @@ def test_multiple_review_clips_no_gap(): # 10 head black frames generated from gap (991-1000) '/path/to/ffmpeg -t 0.4 -r 25.0 -f lavfi' ' -i color=c=black:s=1280x720 -tune ' - 'stillimage -start_number 991 C:/result/output.%04d.jpg', + 'stillimage -start_number 991 -pix_fmt rgba C:/result/output.%04d.png', # Alternance 25fps tiff sequence and 24fps exr sequence # for 100 frames each '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1001 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1001 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 24.0 -i ' f'C:\\with_tc{os.sep}output.%04d.exr ' - '-start_number 1102 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1102 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1198 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1198 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 24.0 -i ' f'C:\\with_tc{os.sep}output.%04d.exr ' - '-start_number 1299 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1299 -pix_fmt rgba C:/result/output.%04d.png', # Repeated 25fps tiff sequence multiple times till the end '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1395 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1395 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1496 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1496 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1597 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1597 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1698 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1698 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1799 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1799 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 1900 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1900 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 2001 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 2001 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 2102 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 2102 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 25.0 -i ' f'C:\\no_tc{os.sep}output.%04d.tif ' - '-start_number 2203 C:/result/output.%04d.jpg' + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 2203 -pix_fmt rgba C:/result/output.%04d.png' ] assert calls == expected @@ -323,15 +344,17 @@ def test_multiple_review_clips_with_gap(): # Gap on review track (12 frames) '/path/to/ffmpeg -t 0.5 -r 24.0 -f lavfi' ' -i color=c=black:s=1280x720 -tune ' - 'stillimage -start_number 991 C:/result/output.%04d.jpg', + 'stillimage -start_number 991 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 24.0 -i ' f'C:\\with_tc{os.sep}output.%04d.exr ' - '-start_number 1003 C:/result/output.%04d.jpg', + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1003 -pix_fmt rgba C:/result/output.%04d.png', '/path/to/ffmpeg -start_number 1000 -framerate 24.0 -i ' f'C:\\with_tc{os.sep}output.%04d.exr ' - '-start_number 1091 C:/result/output.%04d.jpg' + '-vf scale=1280:720:flags=lanczos -compression_level 5 ' + '-start_number 1091 -pix_fmt rgba C:/result/output.%04d.png' ] assert calls == expected