File size: 4,134 Bytes
65edd82 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 a1a36a1 c187eb7 65edd82 c187eb7 a1a36a1 c187eb7 65edd82 c187eb7 65edd82 c187eb7 a1a36a1 c187eb7 65edd82 c187eb7 65edd82 c187eb7 a1a36a1 65edd82 a1a36a1 c187eb7 65edd82 c187eb7 65edd82 c187eb7 a1a36a1 65edd82 c187eb7 65edd82 c187eb7 65edd82 c187eb7 65edd82 a1a36a1 65edd82 c187eb7 65edd82 3c55f88 a1a36a1 65edd82 ca80fca |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# ffmpeg_service.py
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') # e.g., 'mp3', 'm4a', 'wav'
if not media_url or not target_format:
return "Missing 'url' or 'format' parameter", 400
temp_dir = tempfile.mkdtemp()
# Use the original format's extension for the input file to help FFmpeg
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]}...")
# 1. Download the raw media file to a temporary file
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.")
# 2. Run FFmpeg conversion
command = [
'ffmpeg',
'-y', # Overwrite output files without asking
'-i', input_file_path,
# Audio-specific options for quality and codec
'-q:a', '0', # Variable bitrate, highest quality
'-map', 'a', # Only include audio streams
# Codec selection based on format
'-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) # 3-minute timeout
conversion_time = time.time()
print(f"[{time.strftime('%H:%M:%S')}] FFmpeg conversion complete. Time taken: {conversion_time - download_time:.2f} seconds.")
# 3. Stream the converted file back
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:
# 4. Cleanup temporary files
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__':
# For local development/testing of the FFmpeg service
# NOTE: When deployed via Docker/Gunicorn on Hugging Face, this block is ignored.
ffmpeg_app.run(host='0.0.0.0', port=7860, debug=True) |