openconvert 0.1.0__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.
openconvert/converter.py DELETED
@@ -1,152 +0,0 @@
1
- """
2
- Main converter module that provides the open_convert function.
3
- """
4
-
5
- import os
6
- import logging
7
- from pathlib import Path
8
- from typing import Optional, Union, List
9
-
10
- from .converters import (
11
- image_converter,
12
- document_converter,
13
- audio_converter,
14
- video_converter,
15
- archive_converter,
16
- model_converter,
17
- code_converter
18
- )
19
-
20
- # Configure logging
21
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
22
- logger = logging.getLogger(__name__)
23
-
24
- # Define conversion categories
25
- CONVERSION_CATEGORIES = {
26
- # Image formats
27
- 'png': 'image', 'jpg': 'image', 'jpeg': 'image', 'bmp': 'image', 'tiff': 'image',
28
- 'gif': 'image', 'ico': 'image', 'svg': 'image', 'webp': 'image',
29
-
30
- # Document formats
31
- 'txt': 'document', 'pdf': 'document', 'docx': 'document', 'rtf': 'document',
32
- 'md': 'document', 'html': 'document', 'csv': 'document', 'xlsx': 'document',
33
- 'epub': 'document',
34
-
35
- # Audio formats
36
- 'mp3': 'audio', 'wav': 'audio', 'ogg': 'audio', 'flac': 'audio', 'aac': 'audio',
37
-
38
- # Video formats
39
- 'mp4': 'video', 'avi': 'video', 'mkv': 'video', 'mov': 'video',
40
-
41
- # Archive formats
42
- 'zip': 'archive', 'rar': 'archive', '7z': 'archive', 'tar': 'archive', 'gz': 'archive',
43
-
44
- # 3D Model formats
45
- 'stl': 'model', 'obj': 'model', 'fbx': 'model', 'ply': 'model',
46
-
47
- # Code and markup formats
48
- 'json': 'code', 'yaml': 'code', 'xml': 'code', 'latex': 'code'
49
- }
50
-
51
- def open_convert(
52
- filepath: Union[str, Path],
53
- source_format: Optional[str] = None,
54
- target_format: str = None,
55
- output_path: Optional[Union[str, Path]] = None,
56
- options: Optional[dict] = None
57
- ) -> str:
58
- """
59
- Convert a file from one format to another.
60
-
61
- Args:
62
- filepath: Path to the source file
63
- source_format: Source file format (if None, will be inferred from file extension)
64
- target_format: Target file format
65
- output_path: Path to save the converted file (if None, will use the same directory as source)
66
- options: Additional conversion options
67
-
68
- Returns:
69
- Path to the converted file
70
-
71
- Raises:
72
- ValueError: If the conversion is not supported or parameters are invalid
73
- FileNotFoundError: If the source file doesn't exist
74
- RuntimeError: If the conversion fails
75
- """
76
- if options is None:
77
- options = {}
78
-
79
- # Convert filepath to Path object
80
- filepath = Path(filepath)
81
-
82
- # Check if file exists
83
- if not filepath.exists():
84
- raise FileNotFoundError(f"Source file not found: {filepath}")
85
-
86
- # Infer source format from file extension if not provided
87
- if source_format is None:
88
- source_format = filepath.suffix.lower().lstrip('.')
89
- if not source_format:
90
- raise ValueError("Could not determine source format from file extension. Please specify source_format.")
91
- else:
92
- source_format = source_format.lower()
93
-
94
- # Ensure target format is provided and lowercase
95
- if target_format is None:
96
- raise ValueError("Target format must be specified")
97
- target_format = target_format.lower()
98
-
99
- # Check if formats are supported
100
- if source_format not in CONVERSION_CATEGORIES:
101
- raise ValueError(f"Unsupported source format: {source_format}")
102
- if target_format not in CONVERSION_CATEGORIES:
103
- raise ValueError(f"Unsupported target format: {target_format}")
104
-
105
- # Determine output path if not provided
106
- if output_path is None:
107
- output_path = filepath.with_suffix(f".{target_format}")
108
- else:
109
- output_path = Path(output_path)
110
- # If output_path is a directory, use the original filename with new extension
111
- if output_path.is_dir():
112
- output_path = output_path / filepath.with_suffix(f".{target_format}").name
113
-
114
- logger.info(f"Converting {filepath} from {source_format} to {target_format}")
115
-
116
- # Determine conversion category and route to appropriate converter
117
- source_category = CONVERSION_CATEGORIES[source_format]
118
- target_category = CONVERSION_CATEGORIES[target_format]
119
-
120
- # Handle conversion based on categories
121
- if source_category == 'image':
122
- if target_category == 'image' or target_format == 'pdf':
123
- return image_converter.convert(filepath, source_format, target_format, output_path, options)
124
-
125
- elif source_category == 'document':
126
- return document_converter.convert(filepath, source_format, target_format, output_path, options)
127
-
128
- elif source_category == 'audio':
129
- if target_category == 'audio':
130
- return audio_converter.convert(filepath, source_format, target_format, output_path, options)
131
- elif target_format == 'txt': # Speech-to-text
132
- return audio_converter.speech_to_text(filepath, output_path, options)
133
-
134
- elif source_category == 'video':
135
- if target_category == 'video' or target_format == 'gif':
136
- return video_converter.convert(filepath, source_format, target_format, output_path, options)
137
- elif target_format == 'mp3': # Audio extraction
138
- return video_converter.extract_audio(filepath, output_path, options)
139
- elif target_format in ['png', 'jpg']: # Frame extraction
140
- return video_converter.extract_frames(filepath, target_format, output_path, options)
141
-
142
- elif source_category == 'archive':
143
- return archive_converter.convert(filepath, source_format, target_format, output_path, options)
144
-
145
- elif source_category == 'model':
146
- return model_converter.convert(filepath, source_format, target_format, output_path, options)
147
-
148
- elif source_category == 'code':
149
- return code_converter.convert(filepath, source_format, target_format, output_path, options)
150
-
151
- # If we get here, the specific conversion is not supported
152
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
@@ -1,3 +0,0 @@
1
- """
2
- Converters package for handling different types of file conversions.
3
- """
@@ -1,277 +0,0 @@
1
- """
2
- Archive converter module for handling archive format conversions.
3
- """
4
-
5
- import logging
6
- import os
7
- import shutil
8
- import tempfile
9
- from pathlib import Path
10
- from typing import Union, Optional, Dict, Any
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- # Define supported conversions
15
- SUPPORTED_CONVERSIONS = {
16
- 'zip': ['rar', '7z', 'tar', 'gz'],
17
- 'rar': ['zip', '7z', 'tar', 'gz'],
18
- '7z': ['zip', 'rar', 'tar', 'gz'],
19
- 'tar': ['zip', 'rar', '7z', 'gz'],
20
- 'gz': ['zip', 'rar', '7z', 'tar']
21
- }
22
-
23
- def convert(
24
- filepath: Union[str, Path],
25
- source_format: str,
26
- target_format: str,
27
- output_path: Union[str, Path],
28
- options: Optional[Dict[str, Any]] = None
29
- ) -> str:
30
- """
31
- Convert an archive from one format to another.
32
-
33
- Args:
34
- filepath: Path to the source archive file
35
- source_format: Source archive format
36
- target_format: Target archive format
37
- output_path: Path to save the converted archive
38
- options: Additional conversion options
39
-
40
- Returns:
41
- Path to the converted archive
42
-
43
- Raises:
44
- ValueError: If the conversion is not supported
45
- RuntimeError: If the conversion fails
46
- """
47
- if options is None:
48
- options = {}
49
-
50
- # Check if conversion is supported
51
- if target_format not in SUPPORTED_CONVERSIONS.get(source_format, []):
52
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
53
-
54
- filepath = Path(filepath)
55
- output_path = Path(output_path)
56
-
57
- try:
58
- # Create a temporary directory for extraction
59
- with tempfile.TemporaryDirectory() as temp_dir:
60
- temp_dir_path = Path(temp_dir)
61
-
62
- # Extract the source archive
63
- extract_dir = _extract_archive(filepath, source_format, temp_dir_path)
64
-
65
- # Create the target archive
66
- return _create_archive(extract_dir, target_format, output_path, options)
67
-
68
- except Exception as e:
69
- logger.error(f"Error converting {filepath} to {target_format}: {str(e)}")
70
- raise RuntimeError(f"Failed to convert {filepath} to {target_format}: {str(e)}")
71
-
72
- def _extract_archive(
73
- filepath: Path,
74
- format: str,
75
- output_dir: Path
76
- ) -> Path:
77
- """Extract an archive to a directory."""
78
- if format == 'zip':
79
- return _extract_zip(filepath, output_dir)
80
- elif format == 'rar':
81
- return _extract_rar(filepath, output_dir)
82
- elif format == '7z':
83
- return _extract_7z(filepath, output_dir)
84
- elif format == 'tar':
85
- return _extract_tar(filepath, output_dir)
86
- elif format == 'gz':
87
- return _extract_gz(filepath, output_dir)
88
- else:
89
- raise ValueError(f"Unsupported archive format for extraction: {format}")
90
-
91
- def _create_archive(
92
- source_dir: Path,
93
- format: str,
94
- output_path: Path,
95
- options: Dict[str, Any]
96
- ) -> str:
97
- """Create an archive from a directory."""
98
- if format == 'zip':
99
- return _create_zip(source_dir, output_path, options)
100
- elif format == 'rar':
101
- return _create_rar(source_dir, output_path, options)
102
- elif format == '7z':
103
- return _create_7z(source_dir, output_path, options)
104
- elif format == 'tar':
105
- return _create_tar(source_dir, output_path, options)
106
- elif format == 'gz':
107
- return _create_gz(source_dir, output_path, options)
108
- else:
109
- raise ValueError(f"Unsupported archive format for creation: {format}")
110
-
111
- def _extract_zip(filepath: Path, output_dir: Path) -> Path:
112
- """Extract a ZIP archive."""
113
- import zipfile
114
-
115
- with zipfile.ZipFile(filepath, 'r') as zip_ref:
116
- zip_ref.extractall(output_dir)
117
-
118
- return output_dir
119
-
120
- def _extract_rar(filepath: Path, output_dir: Path) -> Path:
121
- """Extract a RAR archive."""
122
- try:
123
- import rarfile
124
-
125
- with rarfile.RarFile(filepath) as rf:
126
- rf.extractall(output_dir)
127
-
128
- return output_dir
129
-
130
- except ImportError:
131
- # Try using unrar command-line tool
132
- import subprocess
133
-
134
- try:
135
- cmd = ['unrar', 'x', str(filepath), str(output_dir)]
136
- subprocess.run(cmd, check=True, capture_output=True)
137
- return output_dir
138
-
139
- except subprocess.SubprocessError as e:
140
- raise RuntimeError(f"Failed to extract RAR archive: {str(e)}. Please install rarfile or unrar.")
141
-
142
- def _extract_7z(filepath: Path, output_dir: Path) -> Path:
143
- """Extract a 7Z archive."""
144
- try:
145
- import py7zr
146
-
147
- with py7zr.SevenZipFile(filepath, mode='r') as z:
148
- z.extractall(output_dir)
149
-
150
- return output_dir
151
-
152
- except ImportError:
153
- # Try using 7z command-line tool
154
- import subprocess
155
-
156
- try:
157
- cmd = ['7z', 'x', str(filepath), f'-o{output_dir}']
158
- subprocess.run(cmd, check=True, capture_output=True)
159
- return output_dir
160
-
161
- except subprocess.SubprocessError as e:
162
- raise RuntimeError(f"Failed to extract 7Z archive: {str(e)}. Please install py7zr or 7z.")
163
-
164
- def _extract_tar(filepath: Path, output_dir: Path) -> Path:
165
- """Extract a TAR archive."""
166
- import tarfile
167
-
168
- with tarfile.open(filepath, 'r') as tar:
169
- tar.extractall(output_dir)
170
-
171
- return output_dir
172
-
173
- def _extract_gz(filepath: Path, output_dir: Path) -> Path:
174
- """Extract a GZ archive."""
175
- import gzip
176
- import tarfile
177
-
178
- # Check if it's a tar.gz file
179
- if filepath.name.endswith('.tar.gz') or filepath.name.endswith('.tgz'):
180
- with tarfile.open(filepath, 'r:gz') as tar:
181
- tar.extractall(output_dir)
182
- return output_dir
183
-
184
- # Otherwise, it's a single gzipped file
185
- with gzip.open(filepath, 'rb') as f_in:
186
- output_file = output_dir / filepath.with_suffix('').name
187
- with open(output_file, 'wb') as f_out:
188
- shutil.copyfileobj(f_in, f_out)
189
-
190
- return output_dir
191
-
192
- def _create_zip(source_dir: Path, output_path: Path, options: Dict[str, Any]) -> str:
193
- """Create a ZIP archive."""
194
- import zipfile
195
-
196
- compression = options.get('compression', zipfile.ZIP_DEFLATED)
197
- compression_level = options.get('compression_level', 9) # 0-9, 9 is highest
198
-
199
- with zipfile.ZipFile(output_path, 'w', compression=compression, compresslevel=compression_level) as zipf:
200
- for root, _, files in os.walk(source_dir):
201
- for file in files:
202
- file_path = Path(root) / file
203
- arcname = file_path.relative_to(source_dir)
204
- zipf.write(file_path, arcname)
205
-
206
- return str(output_path)
207
-
208
- def _create_rar(source_dir: Path, output_path: Path, options: Dict[str, Any]) -> str:
209
- """Create a RAR archive."""
210
- # RAR creation requires command-line tool
211
- import subprocess
212
-
213
- try:
214
- # Determine compression level
215
- compression_level = options.get('compression_level', 5) # 0-5, 5 is highest
216
-
217
- cmd = ['rar', f'a{compression_level}', str(output_path), str(source_dir)]
218
- subprocess.run(cmd, check=True, capture_output=True)
219
- return str(output_path)
220
-
221
- except subprocess.SubprocessError as e:
222
- raise RuntimeError(f"Failed to create RAR archive: {str(e)}. Please install rar command-line tool.")
223
-
224
- def _create_7z(source_dir: Path, output_path: Path, options: Dict[str, Any]) -> str:
225
- """Create a 7Z archive."""
226
- try:
227
- import py7zr
228
-
229
- compression_level = options.get('compression_level', 9) # 0-9, 9 is highest
230
-
231
- with py7zr.SevenZipFile(output_path, 'w', compression_level=compression_level) as z:
232
- z.writeall(source_dir)
233
-
234
- return str(output_path)
235
-
236
- except ImportError:
237
- # Try using 7z command-line tool
238
- import subprocess
239
-
240
- try:
241
- compression_level = options.get('compression_level', 9) # 0-9, 9 is highest
242
-
243
- cmd = ['7z', 'a', f'-mx={compression_level}', str(output_path), f'{source_dir}/*']
244
- subprocess.run(cmd, check=True, capture_output=True, shell=True)
245
- return str(output_path)
246
-
247
- except subprocess.SubprocessError as e:
248
- raise RuntimeError(f"Failed to create 7Z archive: {str(e)}. Please install py7zr or 7z.")
249
-
250
- def _create_tar(source_dir: Path, output_path: Path, options: Dict[str, Any]) -> str:
251
- """Create a TAR archive."""
252
- import tarfile
253
-
254
- with tarfile.open(output_path, 'w') as tar:
255
- tar.add(source_dir, arcname=os.path.basename(source_dir))
256
-
257
- return str(output_path)
258
-
259
- def _create_gz(source_dir: Path, output_path: Path, options: Dict[str, Any]) -> str:
260
- """Create a GZ archive."""
261
- import tarfile
262
-
263
- # If there are multiple files, create a tar.gz
264
- files = list(source_dir.glob('*'))
265
- if len(files) > 1 or any(f.is_dir() for f in files):
266
- with tarfile.open(output_path, 'w:gz') as tar:
267
- tar.add(source_dir, arcname='')
268
- else:
269
- # If there's only one file, create a simple .gz
270
- import gzip
271
-
272
- input_file = files[0]
273
- with open(input_file, 'rb') as f_in:
274
- with gzip.open(output_path, 'wb') as f_out:
275
- shutil.copyfileobj(f_in, f_out)
276
-
277
- return str(output_path)
@@ -1,223 +0,0 @@
1
- """
2
- Audio converter module for handling audio format conversions.
3
- """
4
-
5
- import logging
6
- import os
7
- import tempfile
8
- from pathlib import Path
9
- from typing import Union, Optional, Dict, Any
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
- # Define supported conversions
14
- SUPPORTED_CONVERSIONS = {
15
- 'mp3': ['wav', 'ogg', 'flac', 'aac'],
16
- 'wav': ['mp3', 'ogg', 'flac', 'aac'],
17
- 'ogg': ['mp3', 'wav', 'flac', 'aac'],
18
- 'flac': ['mp3', 'wav', 'ogg', 'aac'],
19
- 'aac': ['mp3', 'wav', 'ogg', 'flac']
20
- }
21
-
22
- def convert(
23
- filepath: Union[str, Path],
24
- source_format: str,
25
- target_format: str,
26
- output_path: Union[str, Path],
27
- options: Optional[Dict[str, Any]] = None
28
- ) -> str:
29
- """
30
- Convert an audio file from one format to another.
31
-
32
- Args:
33
- filepath: Path to the source audio file
34
- source_format: Source audio format
35
- target_format: Target audio format
36
- output_path: Path to save the converted audio
37
- options: Additional conversion options
38
-
39
- Returns:
40
- Path to the converted audio
41
-
42
- Raises:
43
- ValueError: If the conversion is not supported
44
- RuntimeError: If the conversion fails
45
- """
46
- if options is None:
47
- options = {}
48
-
49
- # Check if conversion is supported
50
- if target_format not in SUPPORTED_CONVERSIONS.get(source_format, []):
51
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
52
-
53
- filepath = Path(filepath)
54
- output_path = Path(output_path)
55
-
56
- try:
57
- # Try using pydub for audio conversion
58
- return _convert_with_pydub(filepath, source_format, target_format, output_path, options)
59
- except ImportError:
60
- logger.warning("pydub not installed. Trying alternative method...")
61
-
62
- # Try using ffmpeg directly
63
- return _convert_with_ffmpeg(filepath, source_format, target_format, output_path, options)
64
-
65
- def speech_to_text(
66
- filepath: Union[str, Path],
67
- output_path: Union[str, Path],
68
- options: Optional[Dict[str, Any]] = None
69
- ) -> str:
70
- """
71
- Convert speech audio to text.
72
-
73
- Args:
74
- filepath: Path to the source audio file
75
- output_path: Path to save the text file
76
- options: Additional conversion options
77
-
78
- Returns:
79
- Path to the text file
80
-
81
- Raises:
82
- RuntimeError: If the conversion fails
83
- """
84
- if options is None:
85
- options = {}
86
-
87
- filepath = Path(filepath)
88
- output_path = Path(output_path)
89
-
90
- try:
91
- # Try using SpeechRecognition library
92
- import speech_recognition as sr
93
-
94
- # Initialize recognizer
95
- recognizer = sr.Recognizer()
96
-
97
- # Load the audio file
98
- with sr.AudioFile(str(filepath)) as source:
99
- # Adjust for ambient noise
100
- recognizer.adjust_for_ambient_noise(source)
101
-
102
- # Record the audio
103
- audio_data = recognizer.record(source)
104
-
105
- # Recognize speech using Google Speech Recognition
106
- language = options.get('language', 'en-US')
107
- text = recognizer.recognize_google(audio_data, language=language)
108
-
109
- # Write the text to the output file
110
- with open(output_path, 'w', encoding='utf-8') as f:
111
- f.write(text)
112
-
113
- return str(output_path)
114
-
115
- except ImportError:
116
- logger.error("SpeechRecognition library is required for speech-to-text conversion")
117
- raise RuntimeError("SpeechRecognition library is required for speech-to-text conversion. Please install it.")
118
-
119
- except Exception as e:
120
- logger.error(f"Error in speech-to-text conversion: {str(e)}")
121
- raise RuntimeError(f"Failed to convert speech to text: {str(e)}")
122
-
123
- def _convert_with_pydub(
124
- filepath: Path,
125
- source_format: str,
126
- target_format: str,
127
- output_path: Path,
128
- options: Dict[str, Any]
129
- ) -> str:
130
- """Convert audio using pydub library."""
131
- from pydub import AudioSegment
132
-
133
- # Load the audio file
134
- audio = AudioSegment.from_file(str(filepath), format=source_format)
135
-
136
- # Apply audio processing options
137
- if 'volume' in options:
138
- # Adjust volume (in dB)
139
- audio = audio + options['volume']
140
-
141
- if 'speed' in options:
142
- # Change speed (requires ffmpeg with rubberband)
143
- speed = options['speed']
144
- audio = audio._spawn(audio.raw_data, overrides={
145
- "frame_rate": int(audio.frame_rate * speed)
146
- })
147
-
148
- if 'sample_rate' in options:
149
- # Change sample rate
150
- audio = audio.set_frame_rate(options['sample_rate'])
151
-
152
- if 'channels' in options:
153
- # Change number of channels
154
- if options['channels'] == 1:
155
- audio = audio.set_channels(1)
156
- elif options['channels'] == 2:
157
- audio = audio.set_channels(2)
158
-
159
- if 'trim' in options:
160
- # Trim audio (start_ms, end_ms)
161
- start_ms, end_ms = options['trim']
162
- audio = audio[start_ms:end_ms]
163
-
164
- # Set export parameters
165
- export_params = {}
166
-
167
- if 'bitrate' in options:
168
- export_params['bitrate'] = options['bitrate']
169
-
170
- # Export to target format
171
- audio.export(str(output_path), format=target_format, **export_params)
172
-
173
- return str(output_path)
174
-
175
- def _convert_with_ffmpeg(
176
- filepath: Path,
177
- source_format: str,
178
- target_format: str,
179
- output_path: Path,
180
- options: Dict[str, Any]
181
- ) -> str:
182
- """Convert audio using ffmpeg directly."""
183
- import subprocess
184
-
185
- # Basic ffmpeg command
186
- cmd = ['ffmpeg', '-i', str(filepath)]
187
-
188
- # Add options
189
- if 'volume' in options:
190
- # Volume adjustment in dB
191
- cmd.extend(['-filter:a', f'volume={options["volume"]}dB'])
192
-
193
- if 'speed' in options:
194
- # Speed adjustment
195
- cmd.extend(['-filter:a', f'atempo={options["speed"]}'])
196
-
197
- if 'sample_rate' in options:
198
- # Sample rate
199
- cmd.extend(['-ar', str(options['sample_rate'])])
200
-
201
- if 'channels' in options:
202
- # Number of channels
203
- cmd.extend(['-ac', str(options['channels'])])
204
-
205
- if 'bitrate' in options:
206
- # Bitrate
207
- cmd.extend(['-b:a', options['bitrate']])
208
-
209
- if 'trim' in options:
210
- # Trim (start_seconds, duration_seconds)
211
- start_sec, duration_sec = options['trim']
212
- cmd.extend(['-ss', str(start_sec), '-t', str(duration_sec)])
213
-
214
- # Add output file
215
- cmd.append(str(output_path))
216
-
217
- # Run ffmpeg
218
- try:
219
- subprocess.run(cmd, check=True, capture_output=True)
220
- return str(output_path)
221
- except subprocess.SubprocessError as e:
222
- logger.error(f"Error running ffmpeg: {str(e)}")
223
- raise RuntimeError(f"Failed to convert audio with ffmpeg: {str(e)}")