-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunc.py
More file actions
107 lines (95 loc) · 4.36 KB
/
func.py
File metadata and controls
107 lines (95 loc) · 4.36 KB
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
103
104
105
106
107
import io
import json
import subprocess
import tempfile
import oci
from fdk import response
import os
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def handler(ctx, data: io.BytesIO = None):
temp_path = None
try:
# Parse JSON payload
body = json.loads(data.getvalue() if data else '{}')
bucket_name = body.get('bucket')
object_name = body.get('object')
# Validate input
if not bucket_name or not object_name:
raise ValueError("Missing 'bucket' or 'object' in payload")
# Initialize OCI client
signer = oci.auth.signers.get_resource_principals_signer()
object_client = oci.object_storage.ObjectStorageClient(config={}, signer=signer)
namespace = object_client.get_namespace().data
# Fetch object and infer extension
try:
response_obj = object_client.get_object(namespace, bucket_name, object_name)
file_content = io.BytesIO(response_obj.data.content)
# Get extension from object_name or content-type
file_extension = os.path.splitext(object_name)[1]
if not file_extension:
content_type = response_obj.headers.get('content-type', '')
extension_map = {
'video/mp4': '.mp4',
'video/mpeg': '.mpeg',
'video/x-msvideo': '.avi',
'video/webm': '.webm',
'image/jpeg': '.jpg',
'image/png': '.png',
'audio/mpeg': '.mp3',
'audio/wav': '.wav'
}
file_extension = extension_map.get(content_type, '.mp4')
logger.info(f"Inferred extension {file_extension} from content-type {content_type}")
except oci.exceptions.ServiceError as e:
logger.error(f"OCI Object Storage error: {str(e)}")
return response.Response(ctx, response_data=json.dumps({
"error": f"Failed to fetch object: {str(e)}"
}), status_code=e.status)
# Create temporary file with inferred extension
with tempfile.NamedTemporaryFile(suffix=file_extension, delete=False) as temp_file:
temp_file.write(file_content.read())
temp_path = temp_file.name
logger.info(f"Created temp file: {temp_path}")
# Run ffprobe to extract metadata
cmd = [
'ffprobe', '-v', 'error', '-print_format', 'json',
'-show_format', '-show_streams', temp_path
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
metadata = json.loads(result.stdout)
# Validate metadata
if not metadata.get('format') or not metadata.get('streams'):
logger.error("Invalid multimedia file: no format or streams detected")
return response.Response(ctx, response_data=json.dumps({
"error": "Invalid multimedia file: no format or streams detected"
}), status_code=400)
except (subprocess.CalledProcessError, json.JSONDecodeError) as e:
logger.error(f"ffprobe failed: {str(e)}")
return response.Response(ctx, response_data=json.dumps({
"error": f"FFprobe failed: {str(e)}"
}), status_code=500)
return response.Response(
ctx, response_data=json.dumps(metadata),
headers={"Content-Type": "application/json"}
)
except ValueError as e:
logger.error(f"Input error: {str(e)}")
return response.Response(ctx, response_data=json.dumps({
"error": str(e)
}), status_code=400)
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
return response.Response(ctx, response_data=json.dumps({
"error": f"Unexpected error: {str(e)}"
}), status_code=500)
finally:
if temp_path and os.path.exists(temp_path):
try:
os.unlink(temp_path)
logger.info(f"Cleaned up temp file: {temp_path}")
except Exception as e:
logger.error(f"Failed to clean up temp file {temp_path}: {str(e)}")