| |
|
|
| from flask import Flask, request, Response, stream_with_context |
| import requests |
| import subprocess |
| import tempfile |
| import os |
| import shutil |
| import time |
|
|
| ffmpeg_app = Flask(__name__) |
|
|
| @ffmpeg_app.route('/convert', methods=['GET']) |
| def convert_media(): |
| """ |
| Downloads the raw media file from the provided URL and converts it using FFmpeg. |
| """ |
| media_url = request.args.get('url') |
| target_format = request.args.get('format') |
|
|
| if not media_url or not target_format: |
| return "Missing 'url' or 'format' parameter", 400 |
|
|
| temp_dir = tempfile.mkdtemp() |
| |
| |
| input_ext = media_url.split('.')[-1].split('?')[0] |
| input_file_path = os.path.join(temp_dir, f"input.{input_ext}") |
| output_file_path = os.path.join(temp_dir, f"output.{target_format}") |
|
|
| try: |
| start_time = time.time() |
| print(f"[{time.strftime('%H:%M:%S')}] Starting conversion for {target_format} from URL: {media_url[:100]}...") |
|
|
| |
| with requests.get(media_url, stream=True, timeout=120) as r: |
| r.raise_for_status() |
| content_length = int(r.headers.get('content-length', 0)) |
| print(f"[{time.strftime('%H:%M:%S')}] Raw media size: {content_length/1024/1024:.2f} MB") |
| with open(input_file_path, 'wb') as f: |
| for chunk in r.iter_content(chunk_size=8192): |
| f.write(chunk) |
| |
| download_time = time.time() |
| print(f"[{time.strftime('%H:%M:%S')}] Download complete. Time taken: {download_time - start_time:.2f} seconds.") |
|
|
| |
| command = [ |
| 'ffmpeg', |
| '-y', |
| '-i', input_file_path, |
| |
| '-q:a', '0', |
| '-map', 'a', |
| |
| '-c:a', 'libmp3lame' if target_format == 'mp3' else |
| ('pcm_s16le' if target_format == 'wav' else 'aac'), |
| '-f', target_format, |
| output_file_path |
| ] |
| |
| subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=180) |
| |
| conversion_time = time.time() |
| print(f"[{time.strftime('%H:%M:%S')}] FFmpeg conversion complete. Time taken: {conversion_time - download_time:.2f} seconds.") |
|
|
| |
| def stream_output_file(): |
| with open(output_file_path, 'rb') as f: |
| chunk = True |
| while chunk: |
| chunk = f.read(8192) |
| yield chunk |
|
|
| mime_type = f'audio/{target_format}' if target_format != 'm4a' else 'audio/mp4' |
| |
| return Response(stream_with_context(stream_output_file()), |
| mimetype=mime_type) |
|
|
| except subprocess.CalledProcessError as e: |
| print(f"[{time.strftime('%H:%M:%S')}] FFmpeg command failed with error: {e.stderr.decode()}") |
| return f"Conversion failed: {e.stderr.decode()}", 500 |
| except requests.exceptions.Timeout: |
| return "Media download or conversion timed out.", 504 |
| except Exception as e: |
| print(f"[{time.strftime('%H:%M:%S')}] An error occurred in the FFmpeg service: {e}") |
| return f"Internal Server Error: {e}", 500 |
| |
| finally: |
| |
| if os.path.exists(temp_dir): |
| shutil.rmtree(temp_dir) |
| print(f"[{time.strftime('%H:%M:%S')}] Cleaned up temp directory: {temp_dir}") |
|
|
| @ffmpeg_app.route('/', methods=['GET']) |
| def index(): |
| return "FFmpeg Conversion Service is running." |
|
|
| if __name__ == '__main__': |
| |
| |
| ffmpeg_app.run(host='0.0.0.0', port=7860, debug=True) |