Video editing with Python
This report presents the forensic synthetic code analysis of Zulko/moviepy, a Python project with 14,870 GitHub stars. SynthScan v2.0 examined 21,566 lines of code across 162 source files, recording 243 pattern matches distributed across 13 syntactic categories. The overall adjusted score of 12.8 places this repository in the Low AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 243 distinct pattern matches across 13 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_VideoClip.py | 11 | CODE | |
| LOW | tests/test_videotools.py | 13 | CODE | |
| LOW | tests/test_compositing.py | 9 | CODE | |
| LOW | tests/test_TextClip.py | 9 | CODE | |
| LOW | tests/test_ffmpeg_writer.py | 10 | CODE | |
| LOW | tests/test_issues.py | 9 | CODE | |
| LOW | tests/test_PR.py | 8 | CODE | |
| LOW | tests/test_fx.py | 14 | CODE | |
| LOW | moviepy/__init__.py | 5 | CODE | |
| LOW | moviepy/__init__.py | 6 | CODE | |
| LOW | moviepy/__init__.py | 6 | CODE | |
| LOW | moviepy/__init__.py | 6 | CODE | |
| LOW | moviepy/__init__.py | 12 | CODE | |
| LOW | moviepy/__init__.py | 13 | CODE | |
| LOW | moviepy/__init__.py | 14 | CODE | |
| LOW | moviepy/__init__.py | 15 | CODE | |
| LOW | moviepy/__init__.py | 16 | CODE | |
| LOW | moviepy/__init__.py | 16 | CODE | |
| LOW | moviepy/__init__.py | 17 | CODE | |
| LOW | moviepy/__init__.py | 17 | CODE | |
| LOW | moviepy/__init__.py | 17 | CODE | |
| LOW | moviepy/__init__.py | 22 | CODE | |
| LOW | moviepy/__init__.py | 24 | CODE | |
| LOW | moviepy/__init__.py | 25 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/__init__.py | 26 | CODE | |
| LOW | moviepy/Clip.py | 16 | CODE | |
| LOW | moviepy/video/VideoClip.py | 23 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 5 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 6 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 7 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 8 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 9 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 10 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 11 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 12 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 13 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 14 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 15 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 16 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 17 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 18 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 19 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 20 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 21 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 22 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 23 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 24 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 25 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 26 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 27 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 28 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 29 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 30 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 31 | CODE | |
| LOW | moviepy/video/fx/__init__.py | 32 | CODE | |
| 26 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_VideoClip.py | 77 | def test_write_frame_errors_with_redirected_logs(util, video): | CODE |
| LOW | tests/test_VideoClip.py | 97 | def test_write_videofiles_with_temp_audiofile_path(util): | CODE |
| LOW | tests/test_VideoClip.py | 109 | def test_write_videofiles_audio_codec_error(util, video): | CODE |
| LOW | tests/test_VideoClip.py | 189 | def test_write_image_sequence(util, video): | CODE |
| LOW | tests/test_VideoClip.py | 245 | def test_setaudio_with_audiofile(util): | CODE |
| LOW | tests/test_VideoClip.py | 281 | def test_compositing_with_same_layers(): | CODE |
| LOW | tests/test_VideoClip.py | 306 | def test_setfps_withoutchangeduration(video): | CODE |
| LOW | tests/test_VideoClip.py | 318 | def test_setfps_withchangeduration(video): | CODE |
| LOW | tests/test_VideoClip.py | 330 | def test_copied_videoclip_write_videofile(util): | CODE |
| LOW | tests/test_videotools.py | 1077 | def test_ipython_display_not_available(): | STRING |
| LOW | tests/conftest.py | 81 | def get_functions_with_decorator_defined(code, decorator_name): | CODE |
| LOW | tests/conftest.py | 178 | def functions_with_decorator_defined(): | CODE |
| LOW | tests/test_compositing.py | 47 | def test_clips_array_duration(util): | CODE |
| LOW | tests/test_compositing.py | 78 | def test_concatenate_floating_point(util): | CODE |
| LOW | tests/test_compositing.py | 142 | def test_compositing_with_transparency_colors(util): | CODE |
| LOW | tests/test_compositing.py | 300 | def test_concatenate_with_masks(util): | CODE |
| LOW | tests/test_SubtitlesClip.py | 63 | def test_file_to_subtitles_unicode(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 52 | def test_ffmpeg_parse_infos_video_nframes(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 60 | def test_ffmpeg_parse_infos_no_default_stream(util): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 103 | def test_ffmpeg_parse_infos_decode_file(decode_file, expected_duration): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 136 | def test_ffmpeg_parse_infos_multiple_audio_streams(util, mono_wave): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 204 | def test_ffmpeg_parse_infos_metadata(util, mono_wave): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 258 | def get_value_from_dict_using_lower_key(field, dictionary): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 292 | def test_ffmpeg_parse_infos_chapters(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 309 | def test_ffmpeg_parse_infos_metadata_with_attached_pic(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 330 | def test_ffmpeg_parse_video_rotation(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 336 | def test_correct_video_rotation(util): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 351 | def test_ffmpeg_parse_infos_multiline_metadata(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 520 | def test_not_default_audio_stream_audio_bitrate(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 557 | def test_stream_square_brackets(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 573 | def test_stream_square_brackets_and_language(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 589 | def test_stream_missing_audio_bitrate(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 605 | def test_sequential_frame_pos(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 634 | def test_unusual_order_frame_pos(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 659 | def test_large_skip_frame_pos(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 675 | def test_large_small_skip_equal(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 704 | def test_seeking_beyond_file_end(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 724 | def test_release_of_file_via_close(util): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 759 | def test_failure_to_release_file(util): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 817 | def test_read_transparent_video(): | CODE |
| LOW | tests/test_ffmpeg_reader.py | 533 | def test_stream_deidentation_not_raises_error(): | STRING |
| LOW | tests/test_TextClip.py | 23 | def test_text_filename_arguments_consistence(util): | CODE |
| LOW | tests/test_TextClip.py | 64 | def test_no_text_nor_filename_arguments(method, util): | CODE |
| LOW | tests/test_ffmpeg_writer.py | 258 | def test_write_file_with_spaces(util): | CODE |
| LOW | tests/test_VideoFileClip.py | 50 | def test_copied_videofileclip_write_videofile(util): | CODE |
| LOW | tests/test_VideoFileClip.py | 71 | def test_videofileclip_safe_deepcopy(monkeypatch): | CODE |
| LOW | tests/test_VideoFileClip.py | 89 | def test_ffmpeg_transparency_mask(util): | CODE |
| LOW | tests/test_VideoFileClip.py | 104 | def test_no_duration_raise_io_error(): | CODE |
| LOW | tests/test_VideoFileClip.py | 112 | def test_no_duration_re_encode_can_be_opened(util): | CODE |
| LOW | tests/test_ffmpeg_tools.py | 17 | def test_ffmpeg_extract_subclip(util): | CODE |
| LOW | tests/test_ffmpeg_tools.py | 77 | def test_ffmpeg_stabilize_video(util): | CODE |
| LOW | tests/test_tools.py | 30 | def test_find_extensions_not_found(): | CODE |
| LOW⚡ | tests/test_tools.py | 78 | def test_ffmpeg_escape_filename(given, expected): | CODE |
| LOW⚡ | tests/test_tools.py | 86 | def test_cross_platform_popen_params(os_name, monkeypatch): | CODE |
| LOW⚡ | tests/test_tools.py | 95 | def test_deprecated_version_of(old_name): | CODE |
| LOW | tests/test_tools.py | 189 | def test_decorators_argument_converters_consistency( | CODE |
| LOW | tests/test_AudioClips.py | 54 | def test_concatenate_audioclips_render(util, mono_wave): | CODE |
| LOW | tests/test_AudioClips.py | 147 | def test_concatenate_audioclip_with_audiofileclip(util, stereo_wave): | CODE |
| LOW | tests/test_AudioClips.py | 164 | def test_concatenate_audiofileclips(util): | CODE |
| LOW | tests/test_AudioClips.py | 179 | def test_audioclip_mono_max_volume(mono_wave): | CODE |
| 11 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/conftest.py | 81 | CODE | |
| LOW | tests/conftest.py | 101 | CODE | |
| LOW | tests/test_compositing.py | 182 | CODE | |
| LOW | tests/test_compositing.py | 244 | CODE | |
| LOW | tests/test_tools.py | 189 | CODE | |
| LOW | tests/test_fx.py | 22 | CODE | |
| LOW | tests/test_fx.py | 738 | CODE | |
| LOW | moviepy/video/VideoClip.py | 1436 | CODE | |
| LOW | moviepy/video/VideoClip.py | 1534 | CODE | |
| LOW | moviepy/video/tools/subtitles.py | 177 | CODE | |
| LOW | moviepy/video/tools/drawing.py | 177 | CODE | |
| LOW | moviepy/video/tools/credits.py | 79 | CODE | |
| LOW | moviepy/video/tools/cuts.py | 201 | CODE | |
| LOW | moviepy/video/fx/Resize.py | 58 | CODE | |
| LOW | moviepy/video/fx/Rotate.py | 162 | CODE | |
| LOW | moviepy/video/fx/Rotate.py | 180 | CODE | |
| LOW | moviepy/video/io/ffplay_previewer.py | 91 | CODE | |
| LOW | moviepy/video/io/ffmpeg_writer.py | 262 | CODE | |
| LOW | moviepy/video/io/ffmpeg_writer.py | 181 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 23 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 411 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 464 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 676 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 739 | CODE | |
| LOW | moviepy/video/io/display_in_notebook.py | 54 | CODE | |
| LOW | moviepy/audio/io/ffplay_audiopreviewer.py | 113 | CODE | |
| LOW | moviepy/audio/io/ffmpeg_audiowriter.py | 108 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | moviepy/video/io/ffplay_previewer.py | 0 | closes the writer, terminating the subprocess if is still alive. | STRING |
| HIGH | moviepy/video/io/ffmpeg_writer.py | 0 | closes the writer, terminating the subprocess if is still alive. | STRING |
| HIGH | moviepy/audio/io/ffplay_audiopreviewer.py | 0 | closes the writer, terminating the subprocess if is still alive. | STRING |
| HIGH | moviepy/audio/io/ffmpeg_audiowriter.py | 0 | closes the writer, terminating the subprocess if is still alive. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | moviepy/video/VideoClip.py | 169 | # =============================================================== | COMMENT |
| MEDIUM | moviepy/video/VideoClip.py | 527 | # =============================================================== | COMMENT |
| MEDIUM | moviepy/video/VideoClip.py | 640 | # ----------------------------------------------------------------- | COMMENT |
| MEDIUM | moviepy/video/VideoClip.py | 682 | # -------------------------------------------------------------- | COMMENT |
| MEDIUM | moviepy/video/VideoClip.py | 1208 | # -------------------------------------------------------------- | COMMENT |
| MEDIUM | moviepy/video/VideoClip.py | 1243 | # ---------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | moviepy/video/VideoClip.py | 861 | # Again to understand the math, consider the following to calculate the final mask | COMMENT |
| LOW | moviepy/video/VideoClip.py | 941 | x1_clip = max(-x_start, 0) | COMMENT |
| LOW | docs/conf.py | 41 | COMMENT | |
| LOW | docs/conf.py | 61 | COMMENT | |
| LOW | docs/conf.py | 81 | COMMENT | |
| LOW | docs/conf.py | 141 | COMMENT | |
| LOW | docs/conf.py | 161 | ] | COMMENT |
| LOW | docs/conf.py | 181 | # If false, no index is generated. | COMMENT |
| LOW | docs/conf.py | 201 | # This is the file name suffix for HTML files (e.g. ".xhtml"). | COMMENT |
| LOW | docs/conf.py | 221 | latex_documents = [ | COMMENT |
| LOW | docs/conf.py | 241 | COMMENT | |
| LOW | docs/conf.py | 301 | # The unique identifier of the text. This can be a ISBN number | COMMENT |
| LOW | docs/conf.py | 321 | COMMENT | |
| LOW | …_static/code/user_guide/effects/modify_copy_example.py | 1 | # Import everything needed to edit video clips | COMMENT |
| LOW | …tic/code/getting_started/moviepy_10_minutes/trailer.py | 41 | COMMENT | |
| LOW | …tic/code/getting_started/moviepy_10_minutes/trailer.py | 261 | # Lets finish by modifying our rambo clip to make it sepia | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_ffmpeg_reader.py | 725 | # Create a random video file. | COMMENT |
| MEDIUM | tests/test_ffmpeg_reader.py | 774 | # Create a random video file. | COMMENT |
| MEDIUM | moviepy/video/fx/HeadBlur.py | 32 | # Create a mask for the blur area | COMMENT |
| MEDIUM | moviepy/video/fx/Painting.py | 45 | # Create the darkening effect | COMMENT |
| MEDIUM | docs/_static/code/user_guide/loading/AudioArrayClip.py | 31 | # Create an AudioArrayClip from the audio samples | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | moviepy/config.py | 32 | except Exception as err: | CODE |
| LOW | moviepy/version.py | 5 | except Exception: | CODE |
| LOW | moviepy/video/tools/subtitles.py | 134 | except Exception: | CODE |
| LOW | moviepy/video/tools/subtitles.py | 140 | except Exception: | CODE |
| MEDIUM | moviepy/video/tools/subtitles.py | 131 | def is_in_subclip(t1, t2): | CODE |
| MEDIUM | moviepy/video/tools/subtitles.py | 137 | def try_cropping(t1, t2): | CODE |
| LOW | moviepy/video/io/ffmpeg_reader.py | 523 | except Exception: | CODE |
| LOW | moviepy/video/io/ffmpeg_reader.py | 592 | except Exception: | CODE |
| LOW | moviepy/video/io/ffmpeg_reader.py | 924 | except Exception as exc: | CODE |
| LOW | moviepy/video/io/display_in_notebook.py | 163 | except Exception: | CODE |
| LOW | docs/_static/code/user_guide/loading/closing.py | 8 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | moviepy/video/VideoClip.py | 208 | CODE | |
| LOW | moviepy/video/VideoClip.py | 1176 | CODE | |
| LOW | moviepy/video/VideoClip.py | 1666 | CODE | |
| LOW | moviepy/video/tools/drawing.py | 177 | CODE | |
| LOW | moviepy/video/io/ffmpeg_writer.py | 262 | CODE | |
| LOW | moviepy/video/io/ffmpeg_writer.py | 85 | CODE | |
| LOW | moviepy/video/io/ffmpeg_reader.py | 23 | CODE | |
| LOW | moviepy/video/io/VideoFileClip.py | 91 | CODE | |
| LOW | moviepy/audio/AudioClip.py | 184 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_fx.py | 943 | # Check if the pixel at the specified position matches the expected color | COMMENT |
| LOW | moviepy/video/VideoClip.py | 2102 | # Check if the last font size tested fits within the given width and height | COMMENT |
| LOW | moviepy/video/io/ffmpeg_tools.py | 234 | # Check if the input file exists | COMMENT |
| LOW | moviepy/video/io/ffmpeg_reader.py | 889 | # Open the file in a pipe, read output | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | moviepy/video/io/ffmpeg_reader.py | 275 | # go to the previous integer. This makes the fetching more robust when you | COMMENT |
| LOW | docs/_static/code/user_guide/loading/masks.py | 9 | # To define the VideoClip as a mask, just pass parameter is_mask as True | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | moviepy/__init__.py | 43 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | media/doc_medias/example.txt | 1 | Lorem ipsum | CODE |