78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
import logging
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from urllib.parse import quote
|
|
|
|
from .config import Settings
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class VolcanoOSSUploader:
|
|
"""Upload course videos to Volcano Engine Object Storage (TOS)."""
|
|
|
|
def __init__(self, settings: Settings):
|
|
self.settings = settings
|
|
|
|
@property
|
|
def enabled(self) -> bool:
|
|
return self.settings.volcano_oss_enabled
|
|
|
|
def object_key(self, video_hash: str, stored_filename: str) -> str:
|
|
normalized_hash = video_hash.strip().lower()
|
|
suffix = Path(stored_filename).suffix or ".mp4"
|
|
return f"{self.settings.volcano_oss_key_prefix}{normalized_hash}{suffix}"
|
|
|
|
def public_url(self, object_key: str) -> str:
|
|
return self.settings.volcano_oss_public_url(object_key)
|
|
|
|
def upload(
|
|
self,
|
|
*,
|
|
video_hash: str,
|
|
stored_filename: str,
|
|
local_path: Path,
|
|
content_type: Optional[str] = None,
|
|
) -> str:
|
|
"""Upload one local file and return its permanent public URL."""
|
|
if not self.enabled:
|
|
raise RuntimeError("Volcano OSS is not configured.")
|
|
if not local_path.is_file():
|
|
raise FileNotFoundError(f"Cannot upload a missing video: {local_path}")
|
|
|
|
# Keep the SDK import optional for development machines that do not run
|
|
# the production service. It is declared in sentence_api/requirements.txt.
|
|
try:
|
|
import tos
|
|
except ImportError as exc:
|
|
raise RuntimeError(
|
|
"The Volcano TOS SDK is not installed. Run: pip install tos"
|
|
) from exc
|
|
|
|
object_key = self.object_key(video_hash, stored_filename)
|
|
endpoint = self.settings.volcano_oss_endpoint
|
|
client = tos.TosClientV2(
|
|
self.settings.volcano_oss_access_key,
|
|
self.settings.volcano_oss_secret_key,
|
|
endpoint,
|
|
self.settings.volcano_oss_region,
|
|
)
|
|
try:
|
|
client.put_object_from_file(
|
|
self.settings.volcano_oss_bucket,
|
|
object_key,
|
|
str(local_path),
|
|
)
|
|
except Exception:
|
|
logger.exception(
|
|
"Volcano OSS upload failed: bucket=%s key=%s endpoint=%s",
|
|
self.settings.volcano_oss_bucket,
|
|
object_key,
|
|
endpoint,
|
|
)
|
|
raise
|
|
|
|
logger.info("Uploaded %s to Volcano OSS object %s", local_path.name, object_key)
|
|
return self.public_url(object_key)
|