clipmind 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
clipmind-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mirmudasir692
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: clipmind
3
+ Version: 1.0.0
4
+ Summary: A simple and efficient Python tool to extract audio from video files using FFmpeg
5
+ Author-email: Mudasir <your_email@example.com>
6
+ License: MIT
7
+ Keywords: video,audio,ffmpeg,converter,media
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: annotated-types==0.7.0
15
+ Requires-Dist: anyio==4.13.0
16
+ Requires-Dist: arabic-reshaper==3.0.0
17
+ Requires-Dist: certifi==2026.2.25
18
+ Requires-Dist: cffi==2.0.0
19
+ Requires-Dist: charset-normalizer==3.4.6
20
+ Requires-Dist: cryptography==46.0.6
21
+ Requires-Dist: distro==1.9.0
22
+ Requires-Dist: dnspython==2.8.0
23
+ Requires-Dist: ffmpeg-python==0.2.0
24
+ Requires-Dist: future==1.0.0
25
+ Requires-Dist: google-ai-generativelanguage==0.6.15
26
+ Requires-Dist: google-api-core==2.30.0
27
+ Requires-Dist: google-api-python-client==2.193.0
28
+ Requires-Dist: google-auth==2.49.1
29
+ Requires-Dist: google-auth-httplib2==0.3.0
30
+ Requires-Dist: google-genai==1.68.0
31
+ Requires-Dist: googleapis-common-protos==1.73.1
32
+ Requires-Dist: grpcio==1.78.0
33
+ Requires-Dist: grpcio-status==1.71.2
34
+ Requires-Dist: h11==0.16.0
35
+ Requires-Dist: httpcore==1.0.9
36
+ Requires-Dist: httplib2==0.31.2
37
+ Requires-Dist: httpx==0.28.1
38
+ Requires-Dist: idna==3.11
39
+ Requires-Dist: numpy==2.4.4
40
+ Requires-Dist: opencv-python==4.13.0.92
41
+ Requires-Dist: proto-plus==1.27.2
42
+ Requires-Dist: protobuf==5.29.6
43
+ Requires-Dist: pyasn1==0.6.3
44
+ Requires-Dist: pyasn1_modules==0.4.2
45
+ Requires-Dist: pycparser==3.0
46
+ Requires-Dist: pydantic==2.12.5
47
+ Requires-Dist: pydantic_core==2.41.5
48
+ Requires-Dist: pymongo==4.16.0
49
+ Requires-Dist: pyparsing==3.3.2
50
+ Requires-Dist: python-bidi==0.6.7
51
+ Requires-Dist: python-dotenv==1.2.2
52
+ Requires-Dist: requests==2.33.0
53
+ Requires-Dist: sniffio==1.3.1
54
+ Requires-Dist: tenacity==9.1.4
55
+ Requires-Dist: tqdm==4.67.3
56
+ Requires-Dist: typing-inspection==0.4.2
57
+ Requires-Dist: typing_extensions==4.15.0
58
+ Requires-Dist: uritemplate==4.2.0
59
+ Requires-Dist: urllib3==2.6.3
60
+ Requires-Dist: websockets==16.0
61
+ Dynamic: license-file
62
+
63
+ # clipmind - Video to Audio Converter
64
+
65
+ A simple and efficient Python tool to extract audio from video files using FFmpeg.
66
+
67
+ ## Features
68
+
69
+ - 🎵 Extract high-quality audio (MP3, WAV)
70
+ - ✂️ Video tools: merge, crop, overlay, resolve conversion
71
+ - ✅ File validation and error handling
72
+ - 🖥️ CLI interface and Python library API
73
+ - 🛠️ Minimal dependencies
74
+
75
+ ## Installation
76
+
77
+ ### Prerequisites
78
+
79
+ 1. **Python 3.6+**
80
+ 2. **FFmpeg** (must be in system PATH)
81
+
82
+ ### Install Dependencies
83
+
84
+ ```bash
85
+ pip install ffmpeg-python
86
+ ```
87
+
88
+ ## Usage
89
+
90
+ ### Method 1: Command Line Interface
91
+
92
+ Once installed, use the `clipmind` command:
93
+
94
+ ```bash
95
+ clipmind -i video.mp4 [-o audio.mp3] [-f mp3]
96
+ ```
97
+
98
+ #### Examples:
99
+
100
+ ```bash
101
+ # Basic extraction
102
+ clipmind -i video.mp4
103
+
104
+ # Custom output format
105
+ clipmind -i video.mkv -f wav
106
+ ```
107
+
108
+ ### Method 2: Python Library
109
+
110
+ ```python
111
+ from clipmind import get_audio_from_video
112
+
113
+ # Extract audio
114
+ success = get_audio_from_video("video.mp4", "audio.mp3")
115
+
116
+ # Advanced video tools
117
+ from clipmind import merge_videos, crop_video
118
+ merge_videos("part1.mp4", "part2.mp4", "merged.mp4")
119
+ ```
120
+
121
+ ## Project Structure
122
+
123
+ ```
124
+ clipmind/
125
+ ├── clipmind/ # Core package
126
+ │ └── src/
127
+ │ ├── cli/ # CLI implementation
128
+ │ ├── core/ # Audio & Video tools
129
+ │ └── utils/ # Validations
130
+ ├── pyproject.toml # Build configuration
131
+ └── README.md # Documentation
132
+ ```
133
+
134
+ ## License
135
+
136
+ MIT
@@ -0,0 +1,74 @@
1
+ # clipmind - Video to Audio Converter
2
+
3
+ A simple and efficient Python tool to extract audio from video files using FFmpeg.
4
+
5
+ ## Features
6
+
7
+ - 🎵 Extract high-quality audio (MP3, WAV)
8
+ - ✂️ Video tools: merge, crop, overlay, resolve conversion
9
+ - ✅ File validation and error handling
10
+ - 🖥️ CLI interface and Python library API
11
+ - 🛠️ Minimal dependencies
12
+
13
+ ## Installation
14
+
15
+ ### Prerequisites
16
+
17
+ 1. **Python 3.6+**
18
+ 2. **FFmpeg** (must be in system PATH)
19
+
20
+ ### Install Dependencies
21
+
22
+ ```bash
23
+ pip install ffmpeg-python
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Method 1: Command Line Interface
29
+
30
+ Once installed, use the `clipmind` command:
31
+
32
+ ```bash
33
+ clipmind -i video.mp4 [-o audio.mp3] [-f mp3]
34
+ ```
35
+
36
+ #### Examples:
37
+
38
+ ```bash
39
+ # Basic extraction
40
+ clipmind -i video.mp4
41
+
42
+ # Custom output format
43
+ clipmind -i video.mkv -f wav
44
+ ```
45
+
46
+ ### Method 2: Python Library
47
+
48
+ ```python
49
+ from clipmind import get_audio_from_video
50
+
51
+ # Extract audio
52
+ success = get_audio_from_video("video.mp4", "audio.mp3")
53
+
54
+ # Advanced video tools
55
+ from clipmind import merge_videos, crop_video
56
+ merge_videos("part1.mp4", "part2.mp4", "merged.mp4")
57
+ ```
58
+
59
+ ## Project Structure
60
+
61
+ ```
62
+ clipmind/
63
+ ├── clipmind/ # Core package
64
+ │ └── src/
65
+ │ ├── cli/ # CLI implementation
66
+ │ ├── core/ # Audio & Video tools
67
+ │ └── utils/ # Validations
68
+ ├── pyproject.toml # Build configuration
69
+ └── README.md # Documentation
70
+ ```
71
+
72
+ ## License
73
+
74
+ MIT
@@ -0,0 +1,24 @@
1
+ """Main package file for clipmind."""
2
+
3
+ from .src.core.audio_extractor import get_audio_from_video, extract_audio, get_default_output_path, chunk_video_adaptive
4
+ from .src.core.video_tools import merge_videos, composite_image_over_video, convert_video_resolutions, get_video_thumbnail, detect_video_vulnerability,crop_video, generate_video_summary, generate_subtitle, video_phash
5
+ from .src.utils.validation import validate_video_file, validate_ffmpeg
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "clipmind Team"
9
+ __all__ = [
10
+ "get_audio_from_video",
11
+ "extract_audio",
12
+ "get_default_output_path",
13
+ "validate_video_file",
14
+ "validate_ffmpeg",
15
+ "merge_videos",
16
+ "composite_image_over_video",
17
+ "convert_video_resolutions",
18
+ "get_video_thumbnail",
19
+ "crop_video",
20
+ "chunk_video_adaptive",
21
+ "detect_video_vulnerability",
22
+ "generate_video_summary",
23
+ "generate_subtitle","video_phash"
24
+ ]
@@ -0,0 +1,7 @@
1
+ """Package init file for clipmind."""
2
+ from .core.audio_extractor import get_audio_from_video
3
+ from .utils.language import print_urdu
4
+
5
+ __version__ = "1.0.0"
6
+ __author__ = "clipmind Team"
7
+ __all__ = ["get_audio_from_video", "print_urdu"]
File without changes
@@ -0,0 +1,73 @@
1
+ import argparse
2
+ import sys
3
+ from pathlib import Path
4
+
5
+
6
+ def parse_arguments():
7
+ parser = argparse.ArgumentParser(
8
+ prog="clipmind",
9
+ description="clipmind - Extract audio from video files",
10
+ formatter_class=argparse.RawDescriptionHelpFormatter,
11
+ epilog="""
12
+ Examples:
13
+ clipmind -i video.mp4 # Extract to video.mp3
14
+ clipmind -i video.mp4 -o audio.wav # Extract to audio.wav
15
+ clipmind -i video.mkv -f mp3 # Extract to video.mp3
16
+ """
17
+ )
18
+
19
+ parser.add_argument('-i', '--input', required=True, help='Input video file path')
20
+ parser.add_argument('-o', '--output', help='Output audio file path (optional)')
21
+ parser.add_argument('-f', '--format', choices=['mp3', 'wav'], default='mp3',
22
+ help='Output audio format (default: mp3)')
23
+
24
+ return parser.parse_args()
25
+
26
+
27
+ def show_usage_instructions():
28
+ print("clipmind - Audio Extraction Tool")
29
+ print("==============================")
30
+ print("This tool extracts audio from video files using FFmpeg.")
31
+ print()
32
+ print("Usage: clipmind -i <input_video> [-o <output_audio>] [-f <format>]")
33
+ print()
34
+ print("Options:")
35
+ print(" -i, --input Input video file path (required)")
36
+ print(" -o, --output Output audio file path (optional)")
37
+ print(" -f, --format Output format: mp3 or wav (default: mp3)")
38
+ print()
39
+ print("Example: clipmind -i video.mp4 -o audio.mp3")
40
+
41
+
42
+ def validate_and_get_output_path(input_path, output_path=None, audio_format='mp3'):
43
+ if output_path:
44
+ output_path = Path(output_path)
45
+ else:
46
+ input_path = Path(input_path)
47
+ output_filename = input_path.stem + '.' + audio_format
48
+ output_path = input_path.parent / output_filename
49
+
50
+ output_dir = output_path.parent
51
+ if not output_dir.exists():
52
+ print(f"Error: Output directory does not exist: {output_dir}")
53
+ sys.exit(1)
54
+
55
+ return output_path
56
+
57
+
58
+ def main():
59
+ from ..core.audio_extractor import get_audio_from_video
60
+ args = parse_arguments()
61
+
62
+ success = get_audio_from_video(
63
+ args.input,
64
+ args.output,
65
+ args.format
66
+ )
67
+
68
+ if success:
69
+ print(f"Successfully extracted audio to: {args.output if args.output else 'default path'}")
70
+ sys.exit(0)
71
+ else:
72
+ print("Error: Audio extraction failed.")
73
+ sys.exit(1)
@@ -0,0 +1,4 @@
1
+ """Core module for clipmind package."""
2
+ from .audio_extractor import get_audio_from_video, extract_audio, get_default_output_path
3
+ from .video_tools import merge_videos, composite_image_over_video, convert_video_resolutions, get_video_thumbnail, crop_video, video_phash
4
+ __all__ = ["get_audio_from_video", "extract_audio", "get_default_output_path", "merge_videos", "composite_image_over_video", "convert_video_resolutions", "get_video_thumbnail", "crop_video", "video_phash"]
@@ -0,0 +1,226 @@
1
+ import ffmpeg
2
+ from pathlib import Path
3
+
4
+
5
+ from ..utils.validation import validate_video_file, validate_ffmpeg
6
+ from ..cli.interface import validate_and_get_output_path
7
+ from ..utils.resolution import RESOLUTION_PROFILES
8
+
9
+
10
+ def extract_audio(video_path, output_path, audio_format='mp3', start=None, end=None):
11
+ try:
12
+ audio_codec = 'mp3' if audio_format.lower() == 'mp3' else 'pcm_s16le'
13
+
14
+ input_kwargs = {}
15
+ if start is not None:
16
+ input_kwargs['ss'] = start
17
+ if end is not None:
18
+ input_kwargs['to'] = end
19
+
20
+ stream = ffmpeg.input(str(video_path), **input_kwargs)
21
+ stream = ffmpeg.output(stream, str(output_path), acodec=audio_codec, loglevel='quiet')
22
+
23
+ ffmpeg.run(stream, overwrite_output=True, quiet=True)
24
+
25
+ return True
26
+
27
+ except ImportError:
28
+ return False
29
+ except ffmpeg.Error as e:
30
+ return False
31
+ except Exception as e:
32
+ return False
33
+
34
+ def get_default_output_path(video_path, audio_format='mp3'):
35
+ video_path = Path(video_path)
36
+ output_filename = video_path.stem + '.' + audio_format
37
+ return video_path.parent / output_filename
38
+
39
+
40
+ def get_audio_from_video(video_path, output_path=None, audio_format='mp3', start=None, end=None):
41
+ """
42
+ Library function to extract audio from video.
43
+
44
+ Args:
45
+ video_path (str): Path to the input video file
46
+ output_path (str, optional): Path for the output audio file
47
+ audio_format (str): Audio format ('mp3' or 'wav')
48
+ start (float/str, optional): Start time of the slice (e.g., 10.5 or "00:00:10")
49
+ end (float/str, optional): End time of the slice (e.g., 15.0 or "00:00:15")
50
+
51
+ Returns:
52
+ bool: True if extraction was successful, False otherwise
53
+ """
54
+ if not validate_video_file(video_path):
55
+ return False
56
+
57
+ if not validate_ffmpeg():
58
+ return False
59
+
60
+ output_path = validate_and_get_output_path(video_path, output_path, audio_format)
61
+
62
+ return extract_audio(video_path, str(output_path), audio_format, start, end)
63
+
64
+ def chunk_video_adaptive(video_path, output_dir=None, resolutions=None, segment_duration=10):
65
+ """
66
+ Break video into HLS chunks at multiple resolutions with master manifest.
67
+ Works with both local paths and URLs (http/https).
68
+
69
+ Args:
70
+ video_path (str): Path or URL to input video
71
+ output_dir (str, optional): Directory for output chunks. Default: ./video_chunks/
72
+ resolutions (list): List of resolution keys (e.g., ['360p', '720p']). Default: ['360p', '720p', '1080p']
73
+ segment_duration (int): Target duration of each segment in seconds. Default: 10
74
+
75
+ Returns:
76
+ dict or False: On success returns {
77
+ 'master_manifest': Path, # Path to master.m3u8
78
+ 'output_dir': Path, # Root output directory
79
+ 'variants': { # Dict of generated variants
80
+ '360p': {
81
+ 'manifest': Path, # Path to variant playlist
82
+ 'segments_dir': Path, # Directory containing .ts files
83
+ 'segment_count': int # Number of segments generated
84
+ },
85
+ ...
86
+ }
87
+ }, returns False on failure
88
+ """
89
+ try:
90
+ if not validate_ffmpeg():
91
+ return False
92
+
93
+ # Setup paths
94
+ video_path_str = str(video_path)
95
+ if output_dir is None:
96
+ # Extract filename from URL or path for default naming
97
+ base_name = Path(video_path_str.split('?')[0]).stem or 'video'
98
+ output_dir = Path(f"{base_name}_chunks")
99
+ else:
100
+ output_dir = Path(output_dir)
101
+
102
+ output_dir.mkdir(parents=True, exist_ok=True)
103
+
104
+ # Default resolutions if not specified
105
+ if resolutions is None:
106
+ resolutions = ['360p', '720p', '1080p']
107
+
108
+ # Validate resolutions
109
+ for res in resolutions:
110
+ if res not in RESOLUTION_PROFILES:
111
+ return False
112
+
113
+ variants = {}
114
+
115
+ # Generate chunks for each resolution
116
+ for res_key in resolutions:
117
+ profile = RESOLUTION_PROFILES[res_key]
118
+
119
+ # Create subdirectory for this resolution
120
+ res_dir = output_dir / res_key
121
+ res_dir.mkdir(exist_ok=True)
122
+
123
+ manifest_path = res_dir / "playlist.m3u8"
124
+ segment_pattern = str(res_dir / "segment_%03d.ts")
125
+
126
+ # Build ffmpeg stream
127
+ stream = ffmpeg.input(video_path_str)
128
+
129
+ # Apply scaling and encoding settings
130
+ stream = ffmpeg.filter(stream, 'scale', profile['width'], profile['height'])
131
+
132
+ # HLS output settings
133
+ stream = ffmpeg.output(
134
+ stream,
135
+ str(manifest_path),
136
+ format='hls',
137
+ start_number=0,
138
+ hls_time=segment_duration,
139
+ hls_playlist_type='vod',
140
+ hls_segment_filename=segment_pattern,
141
+ hls_base_url=f"{res_key}/", # Relative path for client resolution
142
+ vcodec='h264',
143
+ acodec='aac',
144
+ video_bitrate=profile['video_bitrate'],
145
+ audio_bitrate=profile['audio_bitrate'],
146
+ preset='fast',
147
+ pix_fmt='yuv420p',
148
+ loglevel='quiet'
149
+ )
150
+
151
+ ffmpeg.run(stream, overwrite_output=True, quiet=True)
152
+
153
+ # Count generated segments
154
+ segments = list(res_dir.glob("segment_*.ts"))
155
+
156
+ variants[res_key] = {
157
+ 'manifest': manifest_path,
158
+ 'segments_dir': res_dir,
159
+ 'segment_count': len(segments)
160
+ }
161
+
162
+ # Generate master playlist
163
+ master_manifest = output_dir / "master.m3u8"
164
+ _write_master_playlist(master_manifest, resolutions, variants)
165
+
166
+ return {
167
+ 'master_manifest': master_manifest,
168
+ 'output_dir': output_dir,
169
+ 'variants': variants
170
+ }
171
+
172
+ except ImportError:
173
+ return False
174
+ except ffmpeg.Error as e:
175
+ return False
176
+ except Exception as e:
177
+ return False
178
+
179
+
180
+ def _write_master_playlist(master_path, resolutions, variants):
181
+ """Generate master HLS playlist referencing all variant playlists."""
182
+ lines = ["#EXTM3U"]
183
+
184
+ for res_key in resolutions:
185
+ profile = RESOLUTION_PROFILES[res_key]
186
+ # Relative path to variant playlist (e.g., "360p/playlist.m3u8")
187
+ variant_path = f"{res_key}/playlist.m3u8"
188
+
189
+ lines.append(
190
+ f"#EXT-X-STREAM-INF:"
191
+ f"BANDWIDTH={profile['bandwidth']},"
192
+ f"RESOLUTION={profile['width']}x{profile['height']},"
193
+ f"NAME=\"{res_key}\""
194
+ )
195
+ lines.append(variant_path)
196
+
197
+ master_path.write_text('\n'.join(lines) + '\n')
198
+
199
+
200
+ def chunk_video_single(video_path, output_dir=None, resolution='720p', segment_duration=10):
201
+ """
202
+ Generate HLS chunks for single resolution only.
203
+
204
+ Args:
205
+ video_path (str): Path or URL to input video
206
+ output_dir (str, optional): Output directory
207
+ resolution (str): Single resolution (e.g., '720p')
208
+ segment_duration (int): Seconds per segment
209
+
210
+ Returns:
211
+ dict or False: {'manifest': Path, 'segments_dir': Path, 'output_dir': Path} or False
212
+ """
213
+ result = chunk_video_adaptive(
214
+ video_path=video_path,
215
+ output_dir=output_dir,
216
+ resolutions=[resolution],
217
+ segment_duration=segment_duration
218
+ )
219
+
220
+ if result:
221
+ return {
222
+ 'manifest': result['variants'][resolution]['manifest'],
223
+ 'segments_dir': result['variants'][resolution]['segments_dir'],
224
+ 'output_dir': result['output_dir']
225
+ }
226
+ return False
@@ -0,0 +1,2 @@
1
+ from .video_validators import validate_video
2
+ __all__ = ["validate_video"]
@@ -0,0 +1,73 @@
1
+ import subprocess
2
+ import os
3
+ import json
4
+
5
+ def validate_video(video_path: str = ""):
6
+ """
7
+ Validates a video file for corruption and malicious structure.
8
+
9
+ Args:
10
+ video_path (str): Path to the video file.
11
+
12
+ Returns:
13
+ tuple: (bool, str) -> (is_valid, reason)
14
+ """
15
+
16
+ if video_path == "":
17
+ raise ValueError("video_path must be provided")
18
+
19
+ if not os.path.exists(video_path):
20
+ return False, "File does not exist."
21
+
22
+ if os.path.getsize(video_path) == 0:
23
+ return False, "File is empty (corrupt)."
24
+ cmd = [
25
+ 'ffprobe',
26
+ '-v', 'error',
27
+ '-show_streams',
28
+ '-select_streams', 'v',
29
+ '-of', 'json',
30
+ video_path
31
+ ]
32
+
33
+ try:
34
+ result = subprocess.run(
35
+ cmd,
36
+ stdout=subprocess.PIPE,
37
+ stderr=subprocess.PIPE,
38
+ text=True,
39
+ timeout=10
40
+ )
41
+ if result.returncode != 0:
42
+ error_msg = result.stderr.strip()
43
+ if not error_msg:
44
+ error_msg = "Unknown parsing error."
45
+ return False, f"File is corrupted or invalid format: {error_msg}"
46
+ try:
47
+ data = json.loads(result.stdout)
48
+ streams = data.get('streams', [])
49
+
50
+ if not streams:
51
+ return False, "Malicious/Invalid: No video stream found. File might be renamed or mislabeled."
52
+
53
+ video_stream = streams[0]
54
+ codec_name = video_stream.get('codec_name', '')
55
+ width = video_stream.get('width', 0)
56
+
57
+ if not codec_name:
58
+ return False, "Invalid video stream detected."
59
+
60
+ if width == 0:
61
+ return False, "Corrupted video metadata (invalid resolution)."
62
+
63
+ except json.JSONDecodeError:
64
+ return False, "Malicious/Corrupt: File structure is unreadable."
65
+ if result.stderr and "Invalid data" in result.stderr:
66
+ return False, f"Warning: File contains corrupted segments. {result.stderr[:100]}"
67
+
68
+ return True, "Video file is valid."
69
+
70
+ except subprocess.TimeoutExpired:
71
+ return False, "Validation timed out. File might be malformed or infinite."
72
+ except Exception as e:
73
+ return False, f"An unexpected error occurred: {str(e)}"