@@ -963,6 +963,21 @@ async def create_ad_creative(
963963 # Track if this is a video creative
964964 is_video = bool (video_id )
965965
966+ # Meta API v24 REQUIRES a thumbnail (image_hash or image_url) in video_data.
967+ # If the caller didn't provide one, auto-fetch from the video object.
968+ if is_video and not thumbnail_url :
969+ try :
970+ video_info = await make_api_request (
971+ video_id , access_token , {"fields" : "picture" }
972+ )
973+ if isinstance (video_info , dict ) and "picture" in video_info :
974+ thumbnail_url = video_info ["picture" ]
975+ logger .info (f"Auto-fetched video thumbnail: { thumbnail_url [:80 ]} ..." )
976+ else :
977+ logger .warning (f"Could not auto-fetch thumbnail for video { video_id } : { video_info } " )
978+ except Exception as e :
979+ logger .warning (f"Failed to auto-fetch thumbnail for video { video_id } : { e } " )
980+
966981 if use_asset_feed :
967982 # Build the media array from the provided source
968983 if is_video :
@@ -1032,11 +1047,12 @@ async def create_ad_creative(
10321047 if is_video :
10331048 # video_data does NOT support "link" directly — URL goes in
10341049 # call_to_action.value.link or is handled by asset_feed_spec.link_urls.
1050+ video_anchor = {"video_id" : video_id }
1051+ if thumbnail_url :
1052+ video_anchor ["image_url" ] = thumbnail_url
10351053 creative_data ["object_story_spec" ] = {
10361054 "page_id" : page_id ,
1037- "video_data" : {
1038- "video_id" : video_id ,
1039- }
1055+ "video_data" : video_anchor
10401056 }
10411057 else :
10421058 creative_data ["object_story_spec" ] = {
@@ -1050,18 +1066,7 @@ async def create_ad_creative(
10501066 # Use object_story_spec with video_data for simple video creatives.
10511067 # NOTE: video_data does NOT support a "link" field directly.
10521068 # The destination URL goes in call_to_action.value.link.
1053-
1054- # Meta API v24 REQUIRES a thumbnail (image_hash or image_url) in video_data.
1055- # If the caller didn't provide one, auto-fetch from the video object.
1056- if not thumbnail_url :
1057- try :
1058- video_info = await make_api_request (
1059- video_id , access_token , {"fields" : "picture" }
1060- )
1061- thumbnail_url = video_info .get ("picture" )
1062- except Exception :
1063- pass # Best-effort; Meta API will return a clear error if missing
1064-
1069+ # Thumbnail auto-fetch is handled earlier (before use_asset_feed branch).
10651070 video_data = {
10661071 "video_id" : video_id ,
10671072 }
@@ -1075,18 +1080,15 @@ async def create_ad_creative(
10751080 if headline :
10761081 video_data ["title" ] = headline
10771082
1078- # NOTE: video_data does NOT support "description" directly.
1079- # For video creatives, description can go in
1080- # call_to_action.value.link_description if needed.
1083+ if description :
1084+ video_data ["description" ] = description
10811085
10821086 # Build call_to_action with the destination URL.
10831087 # For video creatives, link_url MUST go in call_to_action.value.link
10841088 # (not as a top-level field in video_data).
10851089 cta_value = {}
10861090 if link_url :
10871091 cta_value ["link" ] = link_url
1088- if description :
1089- cta_value ["link_description" ] = description
10901092 if lead_gen_form_id :
10911093 cta_value ["lead_gen_form_id" ] = lead_gen_form_id
10921094 cta_type = call_to_action_type or ("LEARN_MORE" if link_url else None )
0 commit comments