180 lines
6.3 KiB
Python
180 lines
6.3 KiB
Python
"""
|
|
Channel Pack Service
|
|
Maps channels to templates, copy frameworks, and platform-specific optimizations.
|
|
"""
|
|
|
|
from typing import Dict, Any, List, Optional
|
|
from loguru import logger
|
|
|
|
from services.image_studio.templates import Platform, TemplateManager
|
|
from services.image_studio.social_optimizer_service import SocialOptimizerService
|
|
|
|
|
|
class ChannelPackService:
|
|
"""Service to build channel-specific asset packs."""
|
|
|
|
def __init__(self):
|
|
"""Initialize Channel Pack Service."""
|
|
self.template_manager = TemplateManager()
|
|
self.social_optimizer = SocialOptimizerService()
|
|
self.logger = logger
|
|
logger.info("[Channel Pack] Service initialized")
|
|
|
|
def get_channel_pack(
|
|
self,
|
|
channel: str,
|
|
asset_type: str = "social_post"
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Get channel-specific pack configuration.
|
|
|
|
Args:
|
|
channel: Target channel (instagram, linkedin, tiktok, facebook, twitter, pinterest, youtube)
|
|
asset_type: Type of asset (social_post, story, reel, cover, etc.)
|
|
|
|
Returns:
|
|
Channel pack configuration with templates, dimensions, copy frameworks
|
|
"""
|
|
try:
|
|
# Map channel string to Platform enum
|
|
platform_map = {
|
|
'instagram': Platform.INSTAGRAM,
|
|
'linkedin': Platform.LINKEDIN,
|
|
'tiktok': Platform.TIKTOK,
|
|
'facebook': Platform.FACEBOOK,
|
|
'twitter': Platform.TWITTER,
|
|
'pinterest': Platform.PINTEREST,
|
|
'youtube': Platform.YOUTUBE,
|
|
}
|
|
|
|
platform = platform_map.get(channel.lower())
|
|
if not platform:
|
|
raise ValueError(f"Unsupported channel: {channel}")
|
|
|
|
# Get templates for this platform
|
|
templates = self.template_manager.get_platform_templates().get(platform, [])
|
|
|
|
# Get platform formats
|
|
formats = self.social_optimizer.get_platform_formats(platform)
|
|
|
|
# Build channel pack
|
|
pack = {
|
|
"channel": channel,
|
|
"platform": platform.value,
|
|
"asset_type": asset_type,
|
|
"templates": [
|
|
{
|
|
"id": t.id,
|
|
"name": t.name,
|
|
"dimensions": f"{t.aspect_ratio.width}x{t.aspect_ratio.height}",
|
|
"aspect_ratio": t.aspect_ratio.ratio,
|
|
"recommended_provider": t.recommended_provider,
|
|
"quality": t.quality,
|
|
}
|
|
for t in templates
|
|
],
|
|
"formats": formats,
|
|
"copy_framework": self._get_copy_framework(channel, asset_type),
|
|
"optimization_tips": self._get_optimization_tips(channel),
|
|
}
|
|
|
|
logger.info(f"[Channel Pack] Built pack for {channel} ({asset_type})")
|
|
return pack
|
|
|
|
except Exception as e:
|
|
logger.error(f"[Channel Pack] Error building pack: {str(e)}")
|
|
return {
|
|
"channel": channel,
|
|
"error": str(e),
|
|
}
|
|
|
|
def _get_copy_framework(
|
|
self,
|
|
channel: str,
|
|
asset_type: str
|
|
) -> Dict[str, Any]:
|
|
"""Get copy framework for channel and asset type."""
|
|
frameworks = {
|
|
"instagram": {
|
|
"social_post": {
|
|
"caption_length": "125-150 words optimal",
|
|
"hashtags": "5-10 relevant hashtags",
|
|
"cta": "Clear call-to-action in first line",
|
|
"emoji": "Use 1-3 emojis strategically",
|
|
},
|
|
"story": {
|
|
"text_overlay": "Keep text minimal, readable at small size",
|
|
"cta": "Swipe-up or link sticker",
|
|
},
|
|
},
|
|
"linkedin": {
|
|
"social_post": {
|
|
"length": "150-300 words for maximum engagement",
|
|
"hashtags": "3-5 professional hashtags",
|
|
"tone": "Professional, thought-leadership focused",
|
|
"cta": "Engage with question or call-to-action",
|
|
},
|
|
},
|
|
"tiktok": {
|
|
"video": {
|
|
"hook": "Strong hook in first 3 seconds",
|
|
"caption": "Short, engaging, use trending hashtags",
|
|
"hashtags": "3-5 trending hashtags",
|
|
},
|
|
},
|
|
}
|
|
|
|
return frameworks.get(channel, {}).get(asset_type, {})
|
|
|
|
def _get_optimization_tips(self, channel: str) -> List[str]:
|
|
"""Get optimization tips for channel."""
|
|
tips = {
|
|
"instagram": [
|
|
"Use square (1:1) or portrait (4:5) for feed posts",
|
|
"Include text overlay safe zones (15% top/bottom, 10% left/right)",
|
|
"Optimize for mobile viewing",
|
|
],
|
|
"linkedin": [
|
|
"Use landscape (1.91:1) for feed posts",
|
|
"Professional photography style",
|
|
"Include clear value proposition",
|
|
],
|
|
"tiktok": [
|
|
"Vertical format (9:16) required",
|
|
"Eye-catching first frame",
|
|
"Fast-paced, engaging content",
|
|
],
|
|
}
|
|
|
|
return tips.get(channel, [])
|
|
|
|
def build_multi_channel_pack(
|
|
self,
|
|
channels: List[str],
|
|
source_image_base64: str
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Build optimized asset pack for multiple channels from single source.
|
|
|
|
Args:
|
|
channels: List of target channels
|
|
source_image_base64: Source image to optimize
|
|
|
|
Returns:
|
|
Multi-channel pack with optimized variants
|
|
"""
|
|
pack_results = []
|
|
|
|
for channel in channels:
|
|
pack = self.get_channel_pack(channel)
|
|
pack_results.append({
|
|
"channel": channel,
|
|
"pack": pack,
|
|
})
|
|
|
|
return {
|
|
"source_image": "provided",
|
|
"channels": pack_results,
|
|
"total_variants": len(channels),
|
|
}
|