Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b242ccc93a | |||
| c6a40331d4 | |||
| 9a71584d6c | |||
| 132de3b652 | |||
| 7e190d4c20 | |||
| df7dbc64d9 | |||
| a55ec273ab | |||
| ec8c480998 | |||
| a2e89da796 | |||
| 3117dfbb30 | |||
| da8c5ab054 | |||
| 9d40536b43 | |||
| 57cf32ac18 | |||
| 66749b7653 | |||
| d83080b628 | |||
| 923ff63a3d | |||
| c2209dec85 | |||
| da03669a99 | |||
| a5aeb58e6c | |||
| 4612abeb9e | |||
| c98509c07a | |||
| 8417709f1a | |||
| d161fc95a8 | |||
| 4e807525e9 | |||
| 47bb987e06 | |||
| d7b9c3ac3b | |||
| c46c51170d | |||
| 81de5ab642 |
-129
@@ -1,129 +0,0 @@
|
||||
# 美家卡智影 - GitLab CI/CD 配置
|
||||
# =======================================
|
||||
# 覆盖范围: 前端多平台构建 (macOS Universal + Windows x64)
|
||||
#
|
||||
# Runner 环境要求:
|
||||
# - macOS runner (标签: macos, arm64):
|
||||
# Apple Silicon Mac, 已安装:
|
||||
# - Xcode Command Line Tools (15+)
|
||||
# - Node.js 22+ (建议通过 nvm 管理)
|
||||
# - Rust 1.94+ (通过 rustup)
|
||||
# - GitLab Runner (shell executor)
|
||||
# - Windows runner (标签: windows, x86_64):
|
||||
# Windows 10/11 x64, 已安装:
|
||||
# - Visual Studio 2022 Build Tools (含 C++ 桌面开发工具链)
|
||||
# - Node.js 22+ (建议通过 nvm-windows 管理)
|
||||
# - Rust 1.94+ (通过 rustup)
|
||||
# - GitLab Runner (shell executor)
|
||||
#
|
||||
# 触发条件: master 分支推送 或 tag 推送
|
||||
# 产物保留: 30 天
|
||||
|
||||
variables:
|
||||
ARTIFACT_EXPIRE_DAYS: "30"
|
||||
|
||||
stages:
|
||||
- build-frontend
|
||||
|
||||
# ==========================================
|
||||
# 通用模板: 前端构建
|
||||
# ==========================================
|
||||
.frontend_build:
|
||||
stage: build-frontend
|
||||
only:
|
||||
- master
|
||||
- tags
|
||||
cache:
|
||||
# Node 依赖缓存(基于 package-lock.json 变更)
|
||||
- key:
|
||||
files:
|
||||
- tauri-app/package-lock.json
|
||||
paths:
|
||||
- tauri-app/node_modules/
|
||||
# Rust 编译缓存(基于 Cargo.lock 变更)
|
||||
- key:
|
||||
files:
|
||||
- tauri-app/src-tauri/Cargo.lock
|
||||
paths:
|
||||
- tauri-app/src-tauri/target/
|
||||
|
||||
# ==========================================
|
||||
# Job: macOS Universal 构建 (ARM64 + Intel)
|
||||
# ==========================================
|
||||
# 说明:
|
||||
# - 在 Apple Silicon Mac 上同时编译 ARM64 和 x86_64 两个架构
|
||||
# - 使用 lipo 合并为 universal Mach-O 可执行文件
|
||||
# - 产物为单一 .dmg,同时支持 M 系列和 Intel Mac
|
||||
build-frontend-macos:
|
||||
extends: .frontend_build
|
||||
tags:
|
||||
- macos
|
||||
- arm64
|
||||
before_script:
|
||||
# 激活 Rust 环境 (rustup 默认安装路径)
|
||||
- source "$HOME/.cargo/env" 2>/dev/null || true
|
||||
# 安装 Intel 目标平台(构建 universal binary 必需)
|
||||
- rustup target add x86_64-apple-darwin
|
||||
# 验证构建环境
|
||||
- node --version
|
||||
- npm --version
|
||||
- cargo --version
|
||||
- rustc --print host
|
||||
script:
|
||||
- cd tauri-app
|
||||
- npm ci
|
||||
# 构建 universal macOS 应用
|
||||
# Tauri 会自动分别编译 aarch64 和 x86_64,再合并为 universal binary
|
||||
- npm run tauri -- build --target universal-apple-darwin
|
||||
artifacts:
|
||||
name: "meijiaka-macos-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}"
|
||||
paths:
|
||||
# DMG 安装包 (推荐用户下载)
|
||||
- tauri-app/src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg
|
||||
# Updater 专用包 + 签名
|
||||
- tauri-app/src-tauri/target/universal-apple-darwin/release/bundle/macos/*.app.tar.gz
|
||||
- tauri-app/src-tauri/target/universal-apple-darwin/release/bundle/macos/*.app.tar.gz.sig
|
||||
expire_in: "${ARTIFACT_EXPIRE_DAYS} days"
|
||||
timeout: 45 minutes
|
||||
retry:
|
||||
max: 1
|
||||
when: runner_system_failure
|
||||
|
||||
# ==========================================
|
||||
# Job: Windows x64 构建
|
||||
# ==========================================
|
||||
# 说明:
|
||||
# - 产物包含 NSIS (.exe) 和 MSI 两种安装包格式
|
||||
# - NSIS 已配置为简体中文安装界面
|
||||
# - sidecar (ffmpeg/ffprobe) 会自动嵌入 .exe 同目录
|
||||
build-frontend-windows:
|
||||
extends: .frontend_build
|
||||
tags:
|
||||
- windows
|
||||
- x86_64
|
||||
before_script:
|
||||
# 验证构建环境
|
||||
- rustc --version
|
||||
- cargo --version
|
||||
- node --version
|
||||
- npm --version
|
||||
script:
|
||||
- cd tauri-app
|
||||
- npm ci
|
||||
# 构建 Windows x64 应用
|
||||
- npm run tauri -- build --target x86_64-pc-windows-msvc
|
||||
artifacts:
|
||||
name: "meijiaka-windows-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}"
|
||||
paths:
|
||||
# Updater 专用包 + 签名
|
||||
- tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
|
||||
- tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe.sig
|
||||
# NSIS 安装包 (推荐用户下载)
|
||||
- tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*-setup.exe
|
||||
# MSI 安装包 (企业部署场景)
|
||||
- tauri-app/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi
|
||||
expire_in: "${ARTIFACT_EXPIRE_DAYS} days"
|
||||
timeout: 45 minutes
|
||||
retry:
|
||||
max: 1
|
||||
when: runner_system_failure
|
||||
@@ -0,0 +1,537 @@
|
||||
diff --git a/python-api/app/api/v1/caption.py b/python-api/app/api/v1/caption.py
|
||||
index afae831..99a771a 100644
|
||||
--- a/python-api/app/api/v1/caption.py
|
||||
+++ b/python-api/app/api/v1/caption.py
|
||||
@@ -24,19 +24,6 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/caption", tags=["Caption"])
|
||||
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
@router.post("/ata/align")
|
||||
async def auto_align_caption(
|
||||
request_body: AutoAlignSubmitRequest,
|
||||
@@ -88,9 +75,3 @@ async def auto_align_caption(
|
||||
except Exception as e:
|
||||
logger.error(f"自动打轴异常: {e}")
|
||||
raise HTTPException(status_code=500, detail="字幕打轴失败,请稍后重试")
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
diff --git a/python-api/app/api/v1/points.py b/python-api/app/api/v1/points.py
|
||||
index b2c7208..23bafa9 100644
|
||||
--- a/python-api/app/api/v1/points.py
|
||||
+++ b/python-api/app/api/v1/points.py
|
||||
@@ -6,7 +6,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
-from datetime import UTC, datetime
|
||||
+from datetime import UTC, datetime, timedelta
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
@@ -14,6 +14,7 @@ from fastapi.responses import JSONResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user, get_db
|
||||
+from app.core.exceptions import InsufficientPointsException
|
||||
from app.crud.point_recharge_order import point_recharge_order
|
||||
from app.crud.point_transaction import point_transaction
|
||||
from app.models.user import User
|
||||
@@ -35,6 +36,7 @@ router = APIRouter(prefix="/points", tags=["Points"])
|
||||
|
||||
# ── 余额查询 ──────────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/balance", response_model=ApiResponse[PointBalanceResponse])
|
||||
async def get_balance(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
@@ -47,6 +49,7 @@ async def get_balance(
|
||||
|
||||
# ── 流水查询 ──────────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/transactions", response_model=ApiResponse[PointTransactionListResponse])
|
||||
async def list_transactions(
|
||||
pagination: PaginationParams = Depends(),
|
||||
@@ -127,12 +130,13 @@ async def list_transactions(
|
||||
|
||||
# ── 充值 ──────────────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.post("/recharge", response_model=ApiResponse[RechargeResponse])
|
||||
async def create_recharge_order(
|
||||
request: RechargeRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
- http_request: Request = None,
|
||||
+ http_request: Request = None, # type: ignore[assignment]
|
||||
):
|
||||
"""
|
||||
创建积分充值订单(微信支付 Native 扫码)
|
||||
@@ -303,9 +307,7 @@ async def handle_wxpay_notify(
|
||||
return _wx_response()
|
||||
|
||||
# 查找订单
|
||||
- order = await point_recharge_order.get_by_out_trade_no(
|
||||
- db, out_trade_no=out_trade_no
|
||||
- )
|
||||
+ order = await point_recharge_order.get_by_out_trade_no(db, out_trade_no=out_trade_no)
|
||||
if not order:
|
||||
logger.error(f"[WechatPay] 回调订单不存在: {out_trade_no}")
|
||||
return _wx_response()
|
||||
@@ -400,9 +402,7 @@ async def query_recharge_status(
|
||||
|
||||
wxpay = get_wxpay_service()
|
||||
async with httpx.AsyncClient(timeout=httpx.Timeout(30.0, connect=10.0)) as client:
|
||||
- wx_result = await wxpay.query_order(
|
||||
- client, out_trade_no=order.out_trade_no
|
||||
- )
|
||||
+ wx_result = await wxpay.query_order(client, out_trade_no=order.out_trade_no)
|
||||
|
||||
order.query_result = str(wx_result)
|
||||
trade_state = wx_result.get("trade_state", "")
|
||||
@@ -465,6 +465,7 @@ async def query_recharge_status(
|
||||
|
||||
# ── 充值档位查询 ──────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/recharge-options", response_model=ApiResponse[list[dict]])
|
||||
async def get_recharge_options(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -480,6 +481,7 @@ async def get_recharge_options(
|
||||
|
||||
# ── 扣费业务类型查询 ──────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/chargeable-types", response_model=ApiResponse[list[str]])
|
||||
async def get_chargeable_types(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -496,6 +498,7 @@ async def get_chargeable_types(
|
||||
|
||||
# ── 积分规则查询 ──────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/rules", response_model=ApiResponse[list[dict]])
|
||||
async def get_points_rules(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -530,9 +533,9 @@ async def get_points_rules(
|
||||
# ── 积分预估查询 ──────────────────────────────────────
|
||||
|
||||
|
||||
-
|
||||
# ── 今日消费统计 ──────────────────────────────────────
|
||||
|
||||
+
|
||||
@router.get("/today-consumed", response_model=ApiResponse[dict])
|
||||
async def get_today_consumed(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
@@ -545,6 +548,7 @@ async def get_today_consumed(
|
||||
|
||||
# ── 直接消费扣费(前端/Rust 层调用)───────────────────
|
||||
|
||||
+
|
||||
@router.post("/consume", response_model=ApiResponse[dict])
|
||||
async def consume_points(
|
||||
request: ConsumeRequest,
|
||||
@@ -569,12 +573,12 @@ async def consume_points(
|
||||
source_type=request.source_type,
|
||||
source_id=request.source_id,
|
||||
description=f"【{request.description or request.source_type}】",
|
||||
- allow_negative=False,
|
||||
+ allow_negative=request.allow_negative,
|
||||
)
|
||||
- except ValueError as e:
|
||||
+ except InsufficientPointsException:
|
||||
# 余额不足(在同一事务内判断,避免竞态)
|
||||
- if "积分不足" in str(e):
|
||||
- raise HTTPException(status_code=402, detail=str(e))
|
||||
+ raise
|
||||
+ except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
await db.commit()
|
||||
|
||||
@@ -587,5 +591,3 @@ async def consume_points(
|
||||
},
|
||||
message="消费成功",
|
||||
)
|
||||
-
|
||||
-
|
||||
diff --git a/python-api/app/api/v1/script.py b/python-api/app/api/v1/script.py
|
||||
index 5e7b18f..26a11a3 100644
|
||||
--- a/python-api/app/api/v1/script.py
|
||||
+++ b/python-api/app/api/v1/script.py
|
||||
@@ -17,6 +17,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.ai.model_router import get_model_router
|
||||
from app.ai.prompts import list_categories, list_prompt_files, load_prompt, render_template
|
||||
from app.api.deps import get_current_user
|
||||
+from app.core.exceptions import AITimeoutException, InsufficientPointsException
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
@@ -71,9 +72,8 @@ async def polish_content(
|
||||
required_points = ps._calculate_cost("polish")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
- raise HTTPException(
|
||||
- status_code=402,
|
||||
- detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
+ raise InsufficientPointsException(
|
||||
+ f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -99,11 +99,11 @@ async def polish_content(
|
||||
data=polished,
|
||||
message=f"{type_name}润色完成",
|
||||
)
|
||||
+ except InsufficientPointsException:
|
||||
+ raise
|
||||
except HTTPException:
|
||||
raise
|
||||
except ValueError as e:
|
||||
- if "积分不足" in str(e):
|
||||
- raise HTTPException(status_code=402, detail=str(e))
|
||||
logger.warning(f"[Polish] 润色失败: {e}")
|
||||
raise HTTPException(status_code=500, detail="润色失败,请检查输入内容后重试")
|
||||
except Exception as e:
|
||||
@@ -111,9 +111,6 @@ async def polish_content(
|
||||
raise HTTPException(status_code=500, detail=f"{type_name}润色失败,请稍后重试")
|
||||
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
@router.post("/generate-title", response_model=ApiResponse[GenerateTitleResponse])
|
||||
async def generate_title(
|
||||
request: GenerateTitleRequest,
|
||||
@@ -146,7 +143,11 @@ async def generate_title(
|
||||
usage_note = "- 视频画面上的标题需要精炼,聚焦核心关键词\n- 副标题与主标题形成呼应,补充说明但不喧宾夺主"
|
||||
|
||||
# 渲染用户提示词
|
||||
- title_type_desc = "大标题(主标题,提炼核心卖点,吸睛)" if request.title_type == "main" else "小标题(副标题,补充说明或制造悬念)"
|
||||
+ title_type_desc = (
|
||||
+ "大标题(主标题,提炼核心卖点,吸睛)"
|
||||
+ if request.title_type == "main"
|
||||
+ else "小标题(副标题,补充说明或制造悬念)"
|
||||
+ )
|
||||
user_prompt = render_template(
|
||||
user_template,
|
||||
title_type=request.title_type,
|
||||
@@ -163,9 +164,8 @@ async def generate_title(
|
||||
required_points = ps._calculate_cost("title")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
- raise HTTPException(
|
||||
- status_code=402,
|
||||
- detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
+ raise InsufficientPointsException(
|
||||
+ f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -179,10 +179,10 @@ async def generate_title(
|
||||
|
||||
title = result.content.strip() if result.content else ""
|
||||
# 去除可能的引号
|
||||
- title = title.strip('"').strip("'").strip('「」').strip('『』').strip('《》')
|
||||
+ title = title.strip('"').strip("'").strip("「」").strip("『』").strip("《》")
|
||||
# 截断到最大长度
|
||||
if len(title) > request.max_length:
|
||||
- title = title[:request.max_length]
|
||||
+ title = title[: request.max_length]
|
||||
|
||||
# 扣费
|
||||
points = ps._calculate_cost("title")
|
||||
@@ -200,15 +200,13 @@ async def generate_title(
|
||||
data=GenerateTitleResponse(title=title),
|
||||
message="标题生成成功",
|
||||
)
|
||||
+ except InsufficientPointsException:
|
||||
+ raise
|
||||
except HTTPException:
|
||||
raise
|
||||
except TimeoutError:
|
||||
logger.warning("[generate_title] 标题生成超时")
|
||||
- raise HTTPException(status_code=500, detail="标题生成超时,请重试")
|
||||
- except ValueError as e:
|
||||
- if "积分不足" in str(e):
|
||||
- raise HTTPException(status_code=402, detail=str(e))
|
||||
- raise HTTPException(status_code=500, detail=f"标题生成失败: {str(e)}")
|
||||
+ raise AITimeoutException("标题生成超时,请稍后重试")
|
||||
except Exception as e:
|
||||
logger.error(f"[generate_title] 标题生成失败: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"标题生成失败: {str(e)}")
|
||||
diff --git a/python-api/app/api/v1/tasks.py b/python-api/app/api/v1/tasks.py
|
||||
index ae17fe3..55965ca 100644
|
||||
--- a/python-api/app/api/v1/tasks.py
|
||||
+++ b/python-api/app/api/v1/tasks.py
|
||||
@@ -18,6 +18,7 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
+from app.core.exceptions import InsufficientPointsException
|
||||
from app.core.redis_client import get_redis_client
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.models.user import User
|
||||
@@ -38,7 +39,6 @@ class ScriptParams(BaseModel):
|
||||
category: str = Field(..., min_length=1, description="大类代码")
|
||||
filename: str = Field(..., min_length=1, description="提示词文件名")
|
||||
|
||||
-
|
||||
@field_validator("category")
|
||||
@classmethod
|
||||
def validate_category(cls, v: str) -> str:
|
||||
@@ -96,7 +96,9 @@ class VideoParams(BaseModel):
|
||||
volume: int = Field(default=0, ge=0, le=10, description="音量")
|
||||
ref_photo_url: str | None = Field(default=None, description="人脸参考图 URL")
|
||||
planned_duration: float = Field(..., gt=0, description="该分镜脚本规划时长(秒),用于余额预检")
|
||||
- total_planned_duration: float = Field(..., gt=0, description="所有分镜规划时长之和(秒),用于预检")
|
||||
+ total_planned_duration: float = Field(
|
||||
+ ..., gt=0, description="所有分镜规划时长之和(秒),用于预检"
|
||||
+ )
|
||||
batch_id: str | None = Field(default=None, description="批次ID(可选)")
|
||||
|
||||
@field_validator("video_url")
|
||||
@@ -134,6 +136,7 @@ class TaskStatusResponse(BaseModel):
|
||||
total: int = Field(0, description="总子任务数")
|
||||
result: dict | None = Field(None, description="任务结果(完成时)")
|
||||
error: str | None = Field(None, description="错误信息(失败时)")
|
||||
+ error_code: str | None = Field(None, description="错误码(失败时,如 content_violation)")
|
||||
created_at: str = Field("", description="任务创建时间(ISO格式)")
|
||||
|
||||
|
||||
@@ -222,9 +225,8 @@ async def create_task(
|
||||
f"[API] 积分不足: user={user_id}, type={task_type}, "
|
||||
f"required={required_points}, balance={check['balance']}"
|
||||
)
|
||||
- raise HTTPException(
|
||||
- status_code=402,
|
||||
- detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
+ raise InsufficientPointsException(
|
||||
+ f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
# ── 3. 写入 Redis ──────────────────────────────────
|
||||
@@ -246,18 +248,41 @@ async def create_task(
|
||||
params=validated_params,
|
||||
)
|
||||
await registry.add_running(task_id)
|
||||
-
|
||||
- logger.info(f"[API] Task created: {task_id}, type={task_type}, user={user_id}")
|
||||
- return TaskCreateResponse(
|
||||
- task_id=task_id,
|
||||
- status="running",
|
||||
- message=f"{task_type} 任务已创建",
|
||||
- )
|
||||
-
|
||||
except Exception as e:
|
||||
logger.error(f"[API] Failed to update registry: {e}")
|
||||
raise HTTPException(status_code=500, detail="创建任务失败:Redis写入错误")
|
||||
|
||||
+ # ── 4. 脚本生成:Redis 写入成功后再扣费 ─────────────
|
||||
+ if task_type == "script" and required_points > 0:
|
||||
+ try:
|
||||
+ async with AsyncSessionLocal() as db:
|
||||
+ await ps.consume(
|
||||
+ db,
|
||||
+ user_id=user_id,
|
||||
+ points=required_points,
|
||||
+ source_type="script",
|
||||
+ source_id=task_id,
|
||||
+ description="【脚本生成】",
|
||||
+ )
|
||||
+ await db.commit()
|
||||
+ except InsufficientPointsException:
|
||||
+ # 余额不足:将任务标记为失败,避免无费执行
|
||||
+ await registry.update(task_id, status="failed", message="积分不足")
|
||||
+ await registry.remove_running(task_id)
|
||||
+ raise
|
||||
+ except Exception as e:
|
||||
+ logger.error(f"[API] 脚本任务扣费失败: {e}")
|
||||
+ await registry.update(task_id, status="failed", message="扣费失败")
|
||||
+ await registry.remove_running(task_id)
|
||||
+ raise HTTPException(status_code=500, detail="扣费失败,请稍后重试")
|
||||
+
|
||||
+ logger.info(f"[API] Task created: {task_id}, type={task_type}, user={user_id}")
|
||||
+ return TaskCreateResponse(
|
||||
+ task_id=task_id,
|
||||
+ status="running",
|
||||
+ message=f"{task_type} 任务已创建",
|
||||
+ )
|
||||
+
|
||||
|
||||
@router.get("", response_model=list[TaskStatusResponse])
|
||||
async def list_tasks(
|
||||
@@ -294,6 +319,7 @@ async def list_tasks(
|
||||
total=task.total,
|
||||
result=None, # 列表查询不返回 result,避免数据过大
|
||||
error=task.error,
|
||||
+ error_code=task.error_code,
|
||||
created_at=task.created_at,
|
||||
)
|
||||
)
|
||||
@@ -337,6 +363,7 @@ async def get_task_status(
|
||||
total=task.total,
|
||||
result=task.result,
|
||||
error=task.error,
|
||||
+ error_code=task.error_code,
|
||||
created_at=task.created_at,
|
||||
)
|
||||
|
||||
diff --git a/python-api/app/api/v1/vidu.py b/python-api/app/api/v1/vidu.py
|
||||
index c0fb04a..401d8da 100644
|
||||
--- a/python-api/app/api/v1/vidu.py
|
||||
+++ b/python-api/app/api/v1/vidu.py
|
||||
@@ -44,10 +44,12 @@ async def vidu_callback(request: Request):
|
||||
headers_dict = dict(request.headers)
|
||||
|
||||
# 使用 APP_BASE_URL 构建 callback_url,确保与提交任务时传给 Vidu 的一致
|
||||
- #(Nginx 反向代理可能导致 request.url 的 scheme 为 http,与 Vidu 签名时的 https 不一致)
|
||||
+ # (Nginx 反向代理可能导致 request.url 的 scheme 为 http,与 Vidu 签名时的 https 不一致)
|
||||
app_base_url = get_settings().app_base_url
|
||||
callback_url = f"{app_base_url}/api/v1/vidu/callback" if app_base_url else str(request.url)
|
||||
- logger.info(f"[Vidu] 收到回调: request_url={request.url}, callback_url={callback_url}, body={body_bytes.decode('utf-8', errors='replace')[:500]}")
|
||||
+ logger.info(
|
||||
+ f"[Vidu] 收到回调: request_url={request.url}, callback_url={callback_url}, body={body_bytes.decode('utf-8', errors='replace')[:500]}"
|
||||
+ )
|
||||
|
||||
try:
|
||||
task_status = await gateway.handle_webhook(
|
||||
@@ -64,15 +66,13 @@ async def vidu_callback(request: Request):
|
||||
logger.error(f"[Vidu] 回调处理失败: {e}")
|
||||
raise HTTPException(status_code=500, detail="回调处理失败,请稍后重试")
|
||||
|
||||
- logger.info(f"[Vidu] 回调解析完成: state={task_status.state}, result={task_status.result}, error={task_status.error_message}")
|
||||
+ logger.info(
|
||||
+ f"[Vidu] 回调解析完成: state={task_status.state}, result={task_status.result}, error={task_status.error_message}"
|
||||
+ )
|
||||
|
||||
# 2. 通过 platform_task_id 反查 Async Engine 内部 task_id,更新 TaskRegistry
|
||||
- platform_task_id = (
|
||||
- task_status.result.get("task_id") if task_status.result else None
|
||||
- )
|
||||
- video_url = (
|
||||
- task_status.result.get("video_url") if task_status.result else None
|
||||
- )
|
||||
+ platform_task_id = task_status.result.get("task_id") if task_status.result else None
|
||||
+ video_url = task_status.result.get("video_url") if task_status.result else None
|
||||
|
||||
logger.info(f"[Vidu] 准备反查 internal_task_id: platform_task_id={platform_task_id}")
|
||||
|
||||
@@ -121,8 +121,6 @@ async def vidu_callback(request: Request):
|
||||
f"platform={platform_task_id}"
|
||||
)
|
||||
else:
|
||||
- logger.warning(
|
||||
- f"[Vidu] 回调无法反查内部 task_id: platform={platform_task_id}"
|
||||
- )
|
||||
+ logger.warning(f"[Vidu] 回调无法反查内部 task_id: platform={platform_task_id}")
|
||||
|
||||
return success_response(message="回调已接收")
|
||||
diff --git a/python-api/app/api/v1/voice.py b/python-api/app/api/v1/voice.py
|
||||
index ba8cac9..dad2b7b 100644
|
||||
--- a/python-api/app/api/v1/voice.py
|
||||
+++ b/python-api/app/api/v1/voice.py
|
||||
@@ -10,12 +10,13 @@ import logging
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
+
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
-from app.core.exceptions import PlatformError
|
||||
+from app.core.exceptions import InsufficientPointsException, PlatformError
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
@@ -49,7 +50,9 @@ class TTSSynthesizeRequest(BaseModel):
|
||||
class VoiceCloneSubmitRequest(BaseModel):
|
||||
"""声音复刻提交请求"""
|
||||
|
||||
- source_audio_url: str | None = Field(None, description="源音频 URL(5-30秒,mp3/wav,需公开可访问)")
|
||||
+ source_audio_url: str | None = Field(
|
||||
+ None, description="源音频 URL(5-30秒,mp3/wav,需公开可访问)"
|
||||
+ )
|
||||
source_video_url: str | None = Field(None, description="源视频 URL(可选)")
|
||||
video_id: str | None = Field(None, description="历史作品ID(可选)")
|
||||
voice_name: str | None = Field(None, description="自定义音色名称(≤20字符)")
|
||||
@@ -111,7 +114,7 @@ async def synthesize_speech(
|
||||
# 宽松预检:余额为负或零时阻止,避免浪费第三方资源
|
||||
balance_info = await ps.get_user_balance(db, current_user.id)
|
||||
if balance_info["balance"] <= 0:
|
||||
- raise HTTPException(status_code=402, detail="余额不足,请先充值")
|
||||
+ raise InsufficientPointsException("余额不足,请先充值")
|
||||
|
||||
try:
|
||||
audio_url = await service.synthesize(
|
||||
@@ -137,10 +140,8 @@ async def synthesize_speech(
|
||||
allow_negative=True,
|
||||
)
|
||||
await db.commit()
|
||||
- except ValueError as e:
|
||||
- if "积分不足" in str(e):
|
||||
- raise HTTPException(status_code=402, detail=str(e))
|
||||
- logger.error(f"[Voice] TTS 扣费失败: {e}")
|
||||
+ except InsufficientPointsException:
|
||||
+ raise
|
||||
except Exception as e:
|
||||
logger.error(f"[Voice] TTS 扣费失败: {e}")
|
||||
|
||||
@@ -165,7 +166,6 @@ async def synthesize_speech(
|
||||
raise HTTPException(status_code=500, detail="语音合成失败,请稍后重试")
|
||||
|
||||
|
||||
-
|
||||
def _normalize_voice_id(name: str | None) -> str:
|
||||
"""
|
||||
将用户输入的名称规范化为 Vidu 合法的 voice_id。
|
||||
@@ -220,9 +220,8 @@ async def submit_clone_task(
|
||||
required_points = ps._calculate_cost("voice_clone")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
- raise HTTPException(
|
||||
- status_code=402,
|
||||
- detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
+ raise InsufficientPointsException(
|
||||
+ f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -244,10 +243,8 @@ async def submit_clone_task(
|
||||
description="【声音复刻】",
|
||||
)
|
||||
await db.commit()
|
||||
- except ValueError as e:
|
||||
- if "积分不足" in str(e):
|
||||
- raise HTTPException(status_code=402, detail=str(e))
|
||||
- logger.error(f"[Voice] 克隆扣费失败: {e}")
|
||||
+ except InsufficientPointsException:
|
||||
+ raise
|
||||
except Exception as e:
|
||||
logger.error(f"[Voice] 克隆扣费失败: {e}")
|
||||
|
||||
@@ -292,5 +289,3 @@ async def query_clone_task(
|
||||
),
|
||||
message="克隆已完成",
|
||||
)
|
||||
-
|
||||
-
|
||||
@@ -0,0 +1,146 @@
|
||||
diff --git a/python-api/app/core/exceptions.py b/python-api/app/core/exceptions.py
|
||||
index d9970d5..837f8d3 100644
|
||||
--- a/python-api/app/core/exceptions.py
|
||||
+++ b/python-api/app/core/exceptions.py
|
||||
@@ -24,9 +24,16 @@ class AppException(HTTPException):
|
||||
status_code: int,
|
||||
message: str = "操作失败",
|
||||
detail: dict | None = None,
|
||||
+ *,
|
||||
+ error_code: str | None = None,
|
||||
):
|
||||
- super().__init__(status_code=status_code, detail=detail or {})
|
||||
+ body = detail or {}
|
||||
+ body["message"] = message
|
||||
+ if error_code:
|
||||
+ body["error_code"] = error_code
|
||||
+ super().__init__(status_code=status_code, detail=body)
|
||||
self.message = message
|
||||
+ self.error_code = error_code
|
||||
|
||||
|
||||
class NotFoundException(AppException):
|
||||
@@ -44,7 +51,7 @@ class ValidationException(AppException):
|
||||
|
||||
def __init__(self, message: str = "参数验证失败"):
|
||||
super().__init__(
|
||||
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
+ status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||
message=message,
|
||||
)
|
||||
|
||||
@@ -79,6 +86,17 @@ class BusinessException(AppException):
|
||||
)
|
||||
|
||||
|
||||
+class InsufficientPointsException(AppException):
|
||||
+ """积分不足"""
|
||||
+
|
||||
+ def __init__(self, message: str = "积分不足"):
|
||||
+ super().__init__(
|
||||
+ status_code=status.HTTP_402_PAYMENT_REQUIRED,
|
||||
+ message=message,
|
||||
+ error_code="insufficient_points",
|
||||
+ )
|
||||
+
|
||||
+
|
||||
class ModelUnavailableException(AppException):
|
||||
"""AI 模型不可用"""
|
||||
|
||||
@@ -99,6 +117,50 @@ class TaskFailedException(AppException):
|
||||
)
|
||||
|
||||
|
||||
+class PromptNotFoundException(AppException):
|
||||
+ """提示词文件不存在"""
|
||||
+
|
||||
+ def __init__(self, message: str = "未找到提示词"):
|
||||
+ super().__init__(
|
||||
+ status_code=status.HTTP_404_NOT_FOUND,
|
||||
+ message=message,
|
||||
+ error_code="prompt_not_found",
|
||||
+ )
|
||||
+
|
||||
+
|
||||
+class AIEmptyResponseException(AppException):
|
||||
+ """AI 返回内容为空"""
|
||||
+
|
||||
+ def __init__(self, message: str = "AI 返回内容为空"):
|
||||
+ super().__init__(
|
||||
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
+ message=message,
|
||||
+ error_code="empty_result",
|
||||
+ )
|
||||
+
|
||||
+
|
||||
+class AIParseErrorException(AppException):
|
||||
+ """AI 返回内容解析失败"""
|
||||
+
|
||||
+ def __init__(self, message: str = "AI 返回格式解析失败"):
|
||||
+ super().__init__(
|
||||
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
+ message=message,
|
||||
+ error_code="parse_error",
|
||||
+ )
|
||||
+
|
||||
+
|
||||
+class AITimeoutException(AppException):
|
||||
+ """AI 调用超时"""
|
||||
+
|
||||
+ def __init__(self, message: str = "AI 请求超时,请稍后重试"):
|
||||
+ super().__init__(
|
||||
+ status_code=status.HTTP_504_GATEWAY_TIMEOUT,
|
||||
+ message=message,
|
||||
+ error_code="timeout",
|
||||
+ )
|
||||
+
|
||||
+
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 第三方平台异常(PlatformError 体系)
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
@@ -111,14 +173,15 @@ class PlatformErrorType:
|
||||
确保前端和网关能够统一处理。
|
||||
"""
|
||||
|
||||
- RATE_LIMIT = "rate_limit" # 429,可重试
|
||||
- AUTH_FAILED = "auth_failed" # 401/403,不可重试
|
||||
- TIMEOUT = "timeout" # 连接/读取超时,可重试
|
||||
- SERVER_ERROR = "server_error" # 第三方 5xx,可重试
|
||||
- BAD_REQUEST = "bad_request" # 参数错误,不可重试
|
||||
+ RATE_LIMIT = "rate_limit" # 429,可重试
|
||||
+ AUTH_FAILED = "auth_failed" # 401/403,不可重试
|
||||
+ TIMEOUT = "timeout" # 连接/读取超时,可重试
|
||||
+ SERVER_ERROR = "server_error" # 第三方 5xx,可重试
|
||||
+ BAD_REQUEST = "bad_request" # 参数错误,不可重试
|
||||
QUOTA_EXHAUSTED = "quota_exhausted" # 额度用完,不可重试(或延迟重试)
|
||||
- NOT_FOUND = "not_found" # 资源不存在,不可重试
|
||||
- UNKNOWN = "unknown" # 兜底
|
||||
+ NOT_FOUND = "not_found" # 资源不存在,不可重试
|
||||
+ CONTENT_VIOLATION = "content_violation" # 内容安全/审核不通过,不可重试
|
||||
+ UNKNOWN = "unknown" # 兜底
|
||||
|
||||
|
||||
class PlatformError(Exception):
|
||||
@@ -145,12 +208,14 @@ class PlatformError(Exception):
|
||||
retryable: bool = False,
|
||||
error_type: str = PlatformErrorType.UNKNOWN,
|
||||
status_code: int | None = None,
|
||||
+ raw_code: str | None = None,
|
||||
):
|
||||
super().__init__(message)
|
||||
self.platform = platform
|
||||
self.retryable = retryable
|
||||
self.error_type = error_type
|
||||
self.status_code = status_code
|
||||
+ self.raw_code = raw_code
|
||||
|
||||
def to_http_status(self) -> int:
|
||||
"""根据 error_type 和 retryable 返回标准 HTTP 状态码"""
|
||||
@@ -161,6 +226,7 @@ class PlatformError(Exception):
|
||||
PlatformErrorType.AUTH_FAILED: 401,
|
||||
PlatformErrorType.BAD_REQUEST: 400,
|
||||
PlatformErrorType.NOT_FOUND: 404,
|
||||
+ PlatformErrorType.CONTENT_VIOLATION: 400,
|
||||
}
|
||||
if self.error_type in mapping:
|
||||
return mapping[self.error_type]
|
||||
@@ -0,0 +1,345 @@
|
||||
diff --git a/python-api/app/ai/providers/vidu_provider.py b/python-api/app/ai/providers/vidu_provider.py
|
||||
index cab5902..fccfbbf 100644
|
||||
--- a/python-api/app/ai/providers/vidu_provider.py
|
||||
+++ b/python-api/app/ai/providers/vidu_provider.py
|
||||
@@ -24,8 +24,90 @@ from app.core.exceptions import PlatformError, PlatformErrorType
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
-def _map_vidu_error(status: int, message: str) -> PlatformError:
|
||||
- """把 Vidu HTTP 错误映射为标准 PlatformError"""
|
||||
+# Vidu 错误码分类
|
||||
+_VIDU_AUDIT_ERROR_CODES = {
|
||||
+ "TaskPromptPolicyViolation",
|
||||
+ "AuditSubmitIllegal",
|
||||
+ "CreationPolicyViolation",
|
||||
+ "PhotoAuditNotPass",
|
||||
+ "AuditFailed",
|
||||
+ "ImageCheckBodyJointsFailed",
|
||||
+ "ImageCheckFaceFailed",
|
||||
+ "ImageObjectsUndetected",
|
||||
+ "FaceDetectFailure",
|
||||
+ "FaceDetectNotPass",
|
||||
+ "NoFaceDetected",
|
||||
+ "MultiFaceDetected",
|
||||
+}
|
||||
+
|
||||
+_VIDU_RETRYABLE_ERROR_CODES = {
|
||||
+ "InternalServiceFailure",
|
||||
+ "ModelUnavailable",
|
||||
+ "Unknown",
|
||||
+}
|
||||
+
|
||||
+_VIDU_RATE_LIMIT_ERROR_CODES = {
|
||||
+ "QuotaExceeded",
|
||||
+ "TooManyRequests",
|
||||
+ "SystemThrottling",
|
||||
+ "OperationInProcess",
|
||||
+}
|
||||
+
|
||||
+
|
||||
+def _extract_vidu_error_code(message: str | None) -> str | None:
|
||||
+ """从 Vidu 错误信息中提取错误码"""
|
||||
+ if not message:
|
||||
+ return None
|
||||
+ # Vidu 错误码格式:"ErrorCode: 中文描述"
|
||||
+ return message.split(":")[0].strip() or None
|
||||
+
|
||||
+
|
||||
+def _map_vidu_error(
|
||||
+ status: int,
|
||||
+ message: str,
|
||||
+ *,
|
||||
+ err_code: str | None = None,
|
||||
+) -> PlatformError:
|
||||
+ """把 Vidu HTTP 错误映射为标准 PlatformError
|
||||
+
|
||||
+ 优先根据 Vidu 业务错误码(err_code)判断类型,HTTP status 仅作为兜底。
|
||||
+ """
|
||||
+ raw_code = err_code or _extract_vidu_error_code(message)
|
||||
+
|
||||
+ # 1. 内容安全/审核类:不可重试
|
||||
+ if raw_code in _VIDU_AUDIT_ERROR_CODES:
|
||||
+ return PlatformError(
|
||||
+ message=message,
|
||||
+ platform="vidu",
|
||||
+ retryable=False,
|
||||
+ error_type=PlatformErrorType.CONTENT_VIOLATION,
|
||||
+ status_code=status,
|
||||
+ raw_code=raw_code,
|
||||
+ )
|
||||
+
|
||||
+ # 2. 平台内部/模型不可用:可重试
|
||||
+ if raw_code in _VIDU_RETRYABLE_ERROR_CODES:
|
||||
+ return PlatformError(
|
||||
+ message=message,
|
||||
+ platform="vidu",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.SERVER_ERROR,
|
||||
+ status_code=status,
|
||||
+ raw_code=raw_code,
|
||||
+ )
|
||||
+
|
||||
+ # 3. 限流类:可重试
|
||||
+ if raw_code in _VIDU_RATE_LIMIT_ERROR_CODES:
|
||||
+ return PlatformError(
|
||||
+ message=message,
|
||||
+ platform="vidu",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.RATE_LIMIT,
|
||||
+ status_code=status,
|
||||
+ raw_code=raw_code,
|
||||
+ )
|
||||
+
|
||||
+ # 4. HTTP status 兜底
|
||||
mapping = {
|
||||
429: (PlatformErrorType.RATE_LIMIT, True),
|
||||
401: (PlatformErrorType.AUTH_FAILED, False),
|
||||
@@ -43,6 +125,7 @@ def _map_vidu_error(status: int, message: str) -> PlatformError:
|
||||
retryable=retryable,
|
||||
error_type=error_type,
|
||||
status_code=status,
|
||||
+ raw_code=raw_code,
|
||||
)
|
||||
|
||||
|
||||
@@ -66,7 +149,9 @@ class ViduProvider:
|
||||
from app.core.platform_config import get_platform_config_loader
|
||||
|
||||
platform_config = get_platform_config_loader().get_platform("vidu")
|
||||
- self.base_url = (platform_config.base_url if platform_config else "https://api.vidu.cn").rstrip("/")
|
||||
+ self.base_url = (
|
||||
+ platform_config.base_url if platform_config else "https://api.vidu.cn"
|
||||
+ ).rstrip("/")
|
||||
|
||||
if not self.api_key:
|
||||
raise ValueError("Vidu API Key 未配置,请在 .env 中设置 VIDU_API_KEY")
|
||||
@@ -135,9 +220,12 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body, timeout=httpx.Timeout(120.0, connect=5.0))
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
- msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
- logger.error(f"[Vidu TTS] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
- raise _map_vidu_error(resp.status_code, f"Vidu TTS error: {msg}")
|
||||
+ err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
+ msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
+ logger.error(
|
||||
+ f"[Vidu TTS] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
+ )
|
||||
+ raise _map_vidu_error(resp.status_code, f"Vidu TTS error: {msg}", err_code=err_code)
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu TTS] 网络错误: {e}")
|
||||
@@ -182,9 +270,14 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body, timeout=httpx.Timeout(120.0, connect=5.0))
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
- msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
- logger.error(f"[Vidu Clone] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
- raise _map_vidu_error(resp.status_code, f"Vidu clone error: {msg}")
|
||||
+ err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
+ msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
+ logger.error(
|
||||
+ f"[Vidu Clone] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
+ )
|
||||
+ raise _map_vidu_error(
|
||||
+ resp.status_code, f"Vidu clone error: {msg}", err_code=err_code
|
||||
+ )
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu Clone] 网络错误: {e}")
|
||||
@@ -238,9 +331,14 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body)
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
- msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
- logger.error(f"[Vidu LipSync] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
- raise _map_vidu_error(resp.status_code, f"Vidu lip-sync error: {msg}")
|
||||
+ err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
+ msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
+ logger.error(
|
||||
+ f"[Vidu LipSync] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
+ )
|
||||
+ raise _map_vidu_error(
|
||||
+ resp.status_code, f"Vidu lip-sync error: {msg}", err_code=err_code
|
||||
+ )
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu LipSync] 网络错误: {e}")
|
||||
@@ -264,9 +362,14 @@ class ViduProvider:
|
||||
resp = await self.client.get(url)
|
||||
data = resp.json()
|
||||
if resp.status_code != 200:
|
||||
- msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
- logger.error(f"[Vidu Query] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
- raise _map_vidu_error(resp.status_code, f"Vidu query task error: {msg}")
|
||||
+ err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
+ msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
+ logger.error(
|
||||
+ f"[Vidu Query] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
+ )
|
||||
+ raise _map_vidu_error(
|
||||
+ resp.status_code, f"Vidu query task error: {msg}", err_code=err_code
|
||||
+ )
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu Query] 网络错误: {e}")
|
||||
diff --git a/python-api/app/ai/providers/volcengine_caption_provider.py b/python-api/app/ai/providers/volcengine_caption_provider.py
|
||||
index 0f2f271..09ddcc7 100644
|
||||
--- a/python-api/app/ai/providers/volcengine_caption_provider.py
|
||||
+++ b/python-api/app/ai/providers/volcengine_caption_provider.py
|
||||
@@ -37,8 +37,10 @@ def _map_caption_error(status: int, message: str, code: int | None = None) -> Pl
|
||||
if code is not None and code in error_mapping:
|
||||
error_type, retryable = error_mapping[code]
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_caption",
|
||||
- retryable=retryable, error_type=error_type,
|
||||
+ message,
|
||||
+ platform="volcengine_caption",
|
||||
+ retryable=retryable,
|
||||
+ error_type=error_type,
|
||||
status_code=status,
|
||||
)
|
||||
|
||||
@@ -53,8 +55,10 @@ def _map_caption_error(status: int, message: str, code: int | None = None) -> Pl
|
||||
}
|
||||
error_type, retryable = http_mapping.get(status, (PlatformErrorType.UNKNOWN, False))
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_caption",
|
||||
- retryable=retryable, error_type=error_type,
|
||||
+ message,
|
||||
+ platform="volcengine_caption",
|
||||
+ retryable=retryable,
|
||||
+ error_type=error_type,
|
||||
status_code=status,
|
||||
)
|
||||
|
||||
@@ -124,7 +128,7 @@ class VolcengineCaptionProvider:
|
||||
max_lines: int = 1,
|
||||
) -> dict[str, Any]:
|
||||
"""提交字幕生成任务,返回 {id: task_id}"""
|
||||
- params = {
|
||||
+ params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"language": language,
|
||||
"caption_type": caption_type,
|
||||
@@ -150,11 +154,15 @@ class VolcengineCaptionProvider:
|
||||
except PlatformError:
|
||||
raise
|
||||
except httpx.HTTPStatusError as e:
|
||||
- raise _map_caption_error(e.response.status_code, f"HTTP错误: {e.response.status_code}") from e
|
||||
+ raise _map_caption_error(
|
||||
+ e.response.status_code, f"HTTP错误: {e.response.status_code}"
|
||||
+ ) from e
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
raise PlatformError(
|
||||
- f"字幕服务网络错误: {e}", platform="volcengine_caption",
|
||||
- retryable=True, error_type=PlatformErrorType.TIMEOUT,
|
||||
+ f"字幕服务网络错误: {e}",
|
||||
+ platform="volcengine_caption",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.TIMEOUT,
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise _map_caption_error(500, f"提交任务失败: {str(e)}") from e
|
||||
@@ -165,7 +173,7 @@ class VolcengineCaptionProvider:
|
||||
blocking: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""查询字幕任务结果,返回原始 JSON"""
|
||||
- params = {
|
||||
+ params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"id": task_id,
|
||||
"blocking": 1 if blocking else 0,
|
||||
@@ -182,11 +190,15 @@ class VolcengineCaptionProvider:
|
||||
except PlatformError:
|
||||
raise
|
||||
except httpx.HTTPStatusError as e:
|
||||
- raise _map_caption_error(e.response.status_code, f"HTTP错误: {e.response.status_code}") from e
|
||||
+ raise _map_caption_error(
|
||||
+ e.response.status_code, f"HTTP错误: {e.response.status_code}"
|
||||
+ ) from e
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
raise PlatformError(
|
||||
- f"字幕服务网络错误: {e}", platform="volcengine_caption",
|
||||
- retryable=True, error_type=PlatformErrorType.TIMEOUT,
|
||||
+ f"字幕服务网络错误: {e}",
|
||||
+ platform="volcengine_caption",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.TIMEOUT,
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise _map_caption_error(500, f"查询任务失败: {str(e)}") from e
|
||||
@@ -201,7 +213,7 @@ class VolcengineCaptionProvider:
|
||||
sta_punc_mode: int = 3,
|
||||
) -> dict[str, Any]:
|
||||
"""提交自动字幕打轴任务,返回 {id: task_id}"""
|
||||
- params = {
|
||||
+ params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"caption_type": caption_type,
|
||||
"sta_punc_mode": sta_punc_mode,
|
||||
@@ -218,7 +230,9 @@ class VolcengineCaptionProvider:
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
if "id" not in data:
|
||||
- raise _map_caption_error(500, f"提交打轴任务失败: {data.get('message', '未知错误')}")
|
||||
+ raise _map_caption_error(
|
||||
+ 500, f"提交打轴任务失败: {data.get('message', '未知错误')}"
|
||||
+ )
|
||||
return data
|
||||
except PlatformError:
|
||||
raise
|
||||
diff --git a/python-api/app/ai/providers/volcengine_provider.py b/python-api/app/ai/providers/volcengine_provider.py
|
||||
index 0e2a5d5..9f029a0 100644
|
||||
--- a/python-api/app/ai/providers/volcengine_provider.py
|
||||
+++ b/python-api/app/ai/providers/volcengine_provider.py
|
||||
@@ -291,27 +291,40 @@ class VolcengineProvider(LLMProvider):
|
||||
|
||||
if status == 429 or "rate limit" in message.lower():
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_ark", retryable=True,
|
||||
- error_type=PlatformErrorType.RATE_LIMIT, status_code=status,
|
||||
+ message,
|
||||
+ platform="volcengine_ark",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.RATE_LIMIT,
|
||||
+ status_code=status,
|
||||
)
|
||||
elif status in (401, 403) or "authentication" in message.lower():
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_ark", retryable=False,
|
||||
- error_type=PlatformErrorType.AUTH_FAILED, status_code=status,
|
||||
+ message,
|
||||
+ platform="volcengine_ark",
|
||||
+ retryable=False,
|
||||
+ error_type=PlatformErrorType.AUTH_FAILED,
|
||||
+ status_code=status,
|
||||
)
|
||||
elif status and status >= 500:
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_ark", retryable=True,
|
||||
- error_type=PlatformErrorType.SERVER_ERROR, status_code=status,
|
||||
+ message,
|
||||
+ platform="volcengine_ark",
|
||||
+ retryable=True,
|
||||
+ error_type=PlatformErrorType.SERVER_ERROR,
|
||||
+ status_code=status,
|
||||
)
|
||||
elif "timeout" in message.lower() or isinstance(e, TimeoutError):
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_ark", retryable=True,
|
||||
+ message,
|
||||
+ platform="volcengine_ark",
|
||||
+ retryable=True,
|
||||
error_type=PlatformErrorType.TIMEOUT,
|
||||
)
|
||||
else:
|
||||
return PlatformError(
|
||||
- message, platform="volcengine_ark", retryable=False,
|
||||
+ message,
|
||||
+ platform="volcengine_ark",
|
||||
+ retryable=False,
|
||||
error_type=PlatformErrorType.UNKNOWN,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
diff --git a/python-api/app/services/point_service.py b/python-api/app/services/point_service.py
|
||||
index 0e5d79e..709f78d 100644
|
||||
--- a/python-api/app/services/point_service.py
|
||||
+++ b/python-api/app/services/point_service.py
|
||||
@@ -25,7 +25,7 @@ import logging
|
||||
import math
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import TYPE_CHECKING, Any
|
||||
|
||||
import yaml
|
||||
from sqlalchemy import select
|
||||
@@ -33,6 +33,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
+from app.core.exceptions import InsufficientPointsException
|
||||
from app.models.point_batch import PointBatch
|
||||
from app.models.point_transaction import PointTransaction
|
||||
from app.models.user_point import UserPoint
|
||||
@@ -46,11 +47,11 @@ if TYPE_CHECKING:
|
||||
_CONFIG_PATH = Path(__file__).resolve().parents[2] / "config" / "points-config.yaml"
|
||||
|
||||
|
||||
-def _load_points_config() -> dict:
|
||||
+def _load_points_config() -> dict[str, Any]:
|
||||
"""加载积分计费配置。服务启动时读取一次,后续内存中使用。"""
|
||||
if not _CONFIG_PATH.exists():
|
||||
raise FileNotFoundError(f"积分配置文件不存在: {_CONFIG_PATH}")
|
||||
- with open(_CONFIG_PATH, "r", encoding="utf-8") as f:
|
||||
+ with open(_CONFIG_PATH, encoding="utf-8") as f:
|
||||
cfg = yaml.safe_load(f) or {}
|
||||
# 合并为统一的查询字典:source_type -> {"mode": "fixed|duration|free", ...}
|
||||
merged: dict[str, dict] = {}
|
||||
@@ -65,18 +66,22 @@ def _load_points_config() -> dict:
|
||||
return merged
|
||||
|
||||
|
||||
-POINTS_CONFIG: dict[str, dict] = _load_points_config()
|
||||
+POINTS_CONFIG: dict[str, Any] = _load_points_config()
|
||||
|
||||
|
||||
def get_recharge_options() -> list[dict]:
|
||||
"""获取充值档位配置(由后端控制,支持积分赠送)"""
|
||||
- return POINTS_CONFIG.get("_recharge_options", [])
|
||||
+ options = POINTS_CONFIG.get("_recharge_options", [])
|
||||
+ if isinstance(options, list):
|
||||
+ return options
|
||||
+ return []
|
||||
|
||||
|
||||
def get_chargeable_source_types() -> list[str]:
|
||||
"""获取所有需要扣费的业务类型列表(排除免费业务)"""
|
||||
return [
|
||||
- key for key, cfg in POINTS_CONFIG.items()
|
||||
+ key
|
||||
+ for key, cfg in POINTS_CONFIG.items()
|
||||
if not key.startswith("_") and cfg.get("mode") != "free"
|
||||
]
|
||||
|
||||
@@ -163,11 +168,10 @@ def _estimate_max_cost(source_type: str, param: dict | None = None) -> int:
|
||||
|
||||
# ── 余额查询 ──────────────────────────────────────────
|
||||
|
||||
+
|
||||
async def get_user_balance(db: AsyncSession, user_id: UUID | str) -> dict:
|
||||
"""获取用户积分余额快照(实时计算,排除已过期批次)。"""
|
||||
- result = await db.execute(
|
||||
- select(UserPoint).where(UserPoint.user_id == user_id)
|
||||
- )
|
||||
+ result = await db.execute(select(UserPoint).where(UserPoint.user_id == user_id))
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
if not up:
|
||||
@@ -182,8 +186,7 @@ async def get_user_balance(db: AsyncSession, user_id: UUID | str) -> dict:
|
||||
from sqlalchemy import func as _func
|
||||
|
||||
available_result = await db.execute(
|
||||
- select(_func.coalesce(_func.sum(PointBatch.remaining), 0))
|
||||
- .where(
|
||||
+ select(_func.coalesce(_func.sum(PointBatch.remaining), 0)).where(
|
||||
PointBatch.user_id == user_id,
|
||||
PointBatch.remaining > 0,
|
||||
PointBatch.expired_at > _now(),
|
||||
@@ -221,6 +224,7 @@ async def check_balance(
|
||||
|
||||
# ── 充值 ──────────────────────────────────────────────
|
||||
|
||||
+
|
||||
async def recharge(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -247,8 +251,7 @@ async def recharge(
|
||||
# 幂等保护:同一笔订单(order_id)只能充值一次
|
||||
if order_id:
|
||||
existing_result = await db.execute(
|
||||
- select(PointTransaction)
|
||||
- .where(
|
||||
+ select(PointTransaction).where(
|
||||
PointTransaction.source_id == str(order_id),
|
||||
PointTransaction.type == "recharge",
|
||||
)
|
||||
@@ -259,9 +262,7 @@ async def recharge(
|
||||
return existing_tx
|
||||
|
||||
# 1. 获取或创建用户积分账户
|
||||
- result = await db.execute(
|
||||
- select(UserPoint).where(UserPoint.user_id == user_id)
|
||||
- )
|
||||
+ result = await db.execute(select(UserPoint).where(UserPoint.user_id == user_id))
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
if not up:
|
||||
@@ -353,7 +354,7 @@ async def consume(
|
||||
直接扣费(后置计费)。
|
||||
|
||||
业务执行成功后调用,按实际消耗直接扣除余额。
|
||||
- 默认不允许欠费(余额不足时抛出 ValueError)。
|
||||
+ 默认不允许欠费(余额不足时抛出 InsufficientPointsException)。
|
||||
Scheduler 后置扣费等场景可设置 allow_negative=True,允许余额变负。
|
||||
|
||||
:param points: 实际消耗积分(正整数)
|
||||
@@ -383,9 +384,7 @@ async def consume(
|
||||
|
||||
# 2. 获取用户积分账户(加锁)
|
||||
result = await db.execute(
|
||||
- select(UserPoint)
|
||||
- .where(UserPoint.user_id == user_id)
|
||||
- .with_for_update()
|
||||
+ select(UserPoint).where(UserPoint.user_id == user_id).with_for_update()
|
||||
)
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
@@ -404,7 +403,7 @@ async def consume(
|
||||
# 3. 余额检查:用实时可用余额(未过期批次 remaining 总和),避免 expire_batches 延迟导致超扣
|
||||
available = sum(b.remaining for b in batches)
|
||||
if not allow_negative and available < points:
|
||||
- raise ValueError(f"积分不足,当前可用余额 {available},需要 {points} 积分")
|
||||
+ raise InsufficientPointsException(f"积分不足,当前可用余额 {available},需要 {points} 积分")
|
||||
|
||||
remaining_to_deduct = points
|
||||
for batch in batches:
|
||||
@@ -440,6 +439,7 @@ async def consume(
|
||||
|
||||
# ── 过期回收 ──────────────────────────────────────────
|
||||
|
||||
+
|
||||
async def expire_batches(db: AsyncSession) -> int:
|
||||
"""
|
||||
回收过期积分批次。返回过期积分总数。
|
||||
@@ -468,9 +468,7 @@ async def expire_batches(db: AsyncSession) -> int:
|
||||
|
||||
# 获取用户积分账户(加锁)
|
||||
up_result = await db.execute(
|
||||
- select(UserPoint)
|
||||
- .where(UserPoint.user_id == batch.user_id)
|
||||
- .with_for_update()
|
||||
+ select(UserPoint).where(UserPoint.user_id == batch.user_id).with_for_update()
|
||||
)
|
||||
up = up_result.scalar_one_or_none()
|
||||
if not up:
|
||||
diff --git a/python-api/app/services/script_service.py b/python-api/app/services/script_service.py
|
||||
index 49aa4b1..60f58d5 100644
|
||||
--- a/python-api/app/services/script_service.py
|
||||
+++ b/python-api/app/services/script_service.py
|
||||
@@ -7,9 +7,16 @@ import asyncio
|
||||
import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
+from typing import Any
|
||||
|
||||
from app.ai.model_router import get_model_router
|
||||
from app.ai.prompts import load_prompt_file, load_script_user_prompt
|
||||
+from app.core.exceptions import (
|
||||
+ AIEmptyResponseException,
|
||||
+ AIParseErrorException,
|
||||
+ AITimeoutException,
|
||||
+ PromptNotFoundException,
|
||||
+)
|
||||
from app.schemas.script import ScriptShot
|
||||
from app.services.ai_response_utils import (
|
||||
safe_parse_ai_json_response,
|
||||
@@ -22,12 +29,9 @@ logger = logging.getLogger(__name__)
|
||||
class ScriptService:
|
||||
"""脚本生成服务"""
|
||||
|
||||
-
|
||||
def __init__(self):
|
||||
self.prompts_dir = Path(__file__).parent.parent / "ai" / "prompts"
|
||||
|
||||
-
|
||||
-
|
||||
def _load_prompt(self, name: str) -> str:
|
||||
"""加载 Prompt 模板"""
|
||||
prompt_file = self.prompts_dir / f"{name}.txt"
|
||||
@@ -58,7 +62,7 @@ class ScriptService:
|
||||
# 加载 Prompt
|
||||
system_prompt = load_prompt_file(category, filename)
|
||||
if not system_prompt:
|
||||
- raise ValueError(f"未找到提示词: category={category}, filename={filename}")
|
||||
+ raise PromptNotFoundException(f"未找到提示词: category={category}, filename={filename}")
|
||||
|
||||
# 用户提示词
|
||||
user_prompt = load_script_user_prompt(
|
||||
@@ -75,24 +79,26 @@ class ScriptService:
|
||||
)
|
||||
|
||||
if not result.content or not result.content.strip():
|
||||
- raise ValueError("AI 返回内容为空,请检查模型配置或重试")
|
||||
+ raise AIEmptyResponseException("AI 返回内容为空,请检查模型配置或重试")
|
||||
|
||||
success, parsed_data, error_msg = safe_parse_ai_json_response(result.content)
|
||||
|
||||
if not success:
|
||||
- raise ValueError(error_msg or "AI 返回格式错误,无法解析为 JSON")
|
||||
+ raise AIParseErrorException(error_msg or "AI 返回格式错误,无法解析为 JSON")
|
||||
|
||||
try:
|
||||
shots_data = validate_and_normalize_shots(parsed_data)
|
||||
|
||||
if not shots_data:
|
||||
- raise ValueError("AI 返回的分镜数据为空或格式不正确")
|
||||
+ raise AIEmptyResponseException("AI 返回的分镜数据为空或格式不正确")
|
||||
|
||||
shots = [ScriptShot(**shot) for shot in shots_data]
|
||||
return shots
|
||||
|
||||
+ except (AIEmptyResponseException, AIParseErrorException):
|
||||
+ raise
|
||||
except Exception as e:
|
||||
- raise ValueError(f"分镜数据处理失败: {str(e)}")
|
||||
+ raise AIParseErrorException(f"分镜数据处理失败: {str(e)}")
|
||||
|
||||
async def polish_content(
|
||||
self,
|
||||
@@ -144,21 +150,23 @@ class ScriptService:
|
||||
)
|
||||
return result.content.strip()
|
||||
except TimeoutError:
|
||||
- raise ValueError("润色请求超时,请重试")
|
||||
+ raise AITimeoutException("润色请求超时,请重试")
|
||||
+ except (AIEmptyResponseException, AIParseErrorException, AITimeoutException):
|
||||
+ raise
|
||||
except Exception as e:
|
||||
- raise ValueError(f"润色失败: {str(e)}")
|
||||
+ raise AIParseErrorException(f"润色失败: {str(e)}")
|
||||
|
||||
async def check_model_health(self) -> dict:
|
||||
"""检查模型健康状态"""
|
||||
model_router = await get_model_router()
|
||||
health_results = await model_router.health_check()
|
||||
|
||||
- models = []
|
||||
+ models: list[dict[str, Any]] = []
|
||||
available_count = 0
|
||||
- recommended = None
|
||||
+ recommended: dict[str, Any] | None = None
|
||||
|
||||
for _provider_id, health in health_results.items():
|
||||
- model_info = {
|
||||
+ model_info: dict[str, Any] = {
|
||||
"id": health.id,
|
||||
"name": health.name,
|
||||
"is_available": health.is_available,
|
||||
@@ -169,9 +177,12 @@ class ScriptService:
|
||||
|
||||
if health.is_available:
|
||||
available_count += 1
|
||||
- if recommended is None or health.response_time < recommended.get(
|
||||
- "response_time", float("inf")
|
||||
- ):
|
||||
+ current_best = (
|
||||
+ float("inf")
|
||||
+ if recommended is None
|
||||
+ else float(recommended.get("response_time") or float("inf"))
|
||||
+ )
|
||||
+ if health.response_time < current_best:
|
||||
recommended = model_info
|
||||
|
||||
total = len(models)
|
||||
@@ -188,7 +199,6 @@ class ScriptService:
|
||||
"""测试指定模型连接"""
|
||||
model_router = await get_model_router()
|
||||
|
||||
-
|
||||
start_time = time.time()
|
||||
|
||||
try:
|
||||
diff --git a/python-api/app/services/vidu_service.py b/python-api/app/services/vidu_service.py
|
||||
index 054823f..61bbdcd 100644
|
||||
--- a/python-api/app/services/vidu_service.py
|
||||
+++ b/python-api/app/services/vidu_service.py
|
||||
@@ -207,8 +207,9 @@ class ViduService:
|
||||
error_type=PlatformErrorType.BAD_REQUEST,
|
||||
)
|
||||
|
||||
- logger.info(f"[Vidu Clone] 复刻成功: voice_id={result.data.get('voice_id')}")
|
||||
- return result.data or {}
|
||||
+ clone_data = result.data or {}
|
||||
+ logger.info(f"[Vidu Clone] 复刻成功: voice_id={clone_data.get('voice_id')}")
|
||||
+ return clone_data
|
||||
|
||||
async def query_clone_task(self, voice_id: str) -> dict[str, Any]:
|
||||
"""Vidu 声音复刻是同步接口,无独立查询。
|
||||
@@ -270,6 +271,8 @@ class ViduService:
|
||||
result_data = status.result or {}
|
||||
return {
|
||||
"state": ViduAdapter.denormalize_state(status.state),
|
||||
- "creations": [{"url": result_data.get("video_url")}] if result_data.get("video_url") else [],
|
||||
+ "creations": (
|
||||
+ [{"url": result_data.get("video_url")}] if result_data.get("video_url") else []
|
||||
+ ),
|
||||
"message": status.error_message,
|
||||
}
|
||||
diff --git a/python-api/app/services/volcengine_caption_service.py b/python-api/app/services/volcengine_caption_service.py
|
||||
index 83f59b4..9a565a5 100644
|
||||
--- a/python-api/app/services/volcengine_caption_service.py
|
||||
+++ b/python-api/app/services/volcengine_caption_service.py
|
||||
@@ -155,10 +155,7 @@ class VolcengineCaptionService:
|
||||
error_type=PlatformErrorType.BAD_REQUEST,
|
||||
)
|
||||
|
||||
- logger.warning(
|
||||
- f"{task_name}超过最大轮询次数: task_id={task_id}, "
|
||||
- f"retries={retries}"
|
||||
- )
|
||||
+ logger.warning(f"{task_name}超过最大轮询次数: task_id={task_id}, " f"retries={retries}")
|
||||
raise PlatformError(
|
||||
f"{task_name}超时,请稍后重试",
|
||||
platform="volcengine_caption",
|
||||
@@ -9,7 +9,7 @@
|
||||
**美家卡智影**是一款面向桌面端的 AI 视频创作应用,采用"Python 后端 API + Tauri 桌面前端"的混合架构。
|
||||
|
||||
- **产品标识**: `cn.meijiaka.ai-video` / `cn.meijiaka.ai-zy`
|
||||
- **版本**: `1.8.0`
|
||||
- **版本**: `1.9.1`
|
||||
- **核心功能**: AI 脚本生成、AI 配音合成(TTS)、声音复刻、视频生成(Vidu)、视频字幕生成、压制成片(FFmpeg)、项目本地持久化
|
||||
|
||||
### 技术栈总览
|
||||
@@ -25,7 +25,7 @@
|
||||
| 前端构建 | Vite 7 |
|
||||
| 状态管理 | Zustand 5 + Immer 11 |
|
||||
| 路由 | `react-router-dom` |
|
||||
| 数据请求 | 自研智能路由客户端 + SWR |
|
||||
| 数据请求 | HTTP 客户端 (`src/api/client.ts`) + SWR |
|
||||
| 测试(后端) | pytest + pytest-asyncio |
|
||||
| 测试(前端) | Vitest 4 + jsdom + `@testing-library/react` |
|
||||
| 部署 | Docker + Docker Compose + Nginx |
|
||||
@@ -42,7 +42,7 @@
|
||||
├── tauri-app/ # Tauri 桌面前端
|
||||
├── docs/ # 项目文档(架构设计、API 对接指南等)
|
||||
├── scripts/ # 辅助脚本
|
||||
├── .gitlab-ci.yml # GitLab CI/CD 配置
|
||||
├── .github/workflows/ # GitHub Actions CI/CD 配置
|
||||
└── AGENTS.md # 本文档
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
```
|
||||
python-api/
|
||||
├── app/ # 主应用代码
|
||||
│ ├── api/v1/ # API 路由(按领域拆分:auth, script, voice, vidu, caption, tasks, upload, materials, system)
|
||||
│ ├── api/v1/ # API 路由(按领域拆分:auth, script, voice, vidu, caption, tasks, upload, materials, system, bgm_music, cover_background, image, points, update, events)
|
||||
│ ├── core/ # 核心工具(配置加载、安全、异常、Redis 客户端、健康检查)
|
||||
│ ├── db/ # 数据库配置与会话管理
|
||||
│ ├── models/ # SQLAlchemy ORM 模型(BaseModel 提供 UUID 主键 + 时间戳)
|
||||
@@ -62,7 +62,7 @@ python-api/
|
||||
│ ├── crud/ # 数据库 CRUD 封装
|
||||
│ ├── config.py # Pydantic Settings 配置管理
|
||||
│ └── main.py # FastAPI 应用入口(含 lifespan 管理)
|
||||
├── config/ # 运行时配置文件(platform-config.yaml, materials.json)
|
||||
├── config/ # 运行时配置文件(platform-config.yaml, points-config.yaml)
|
||||
├── alembic/ # 数据库迁移脚本
|
||||
├── nginx/ # Nginx 反向代理配置(含 acme.sh SSL 证书脚本)
|
||||
├── Dockerfile # 多阶段构建镜像(builder + production)
|
||||
@@ -81,12 +81,11 @@ python-api/
|
||||
tauri-app/
|
||||
├── src/ # React 前端源码
|
||||
│ ├── api/ # API 客户端与模块
|
||||
│ │ ├── client.ts # 智能路由客户端(HTTP / IPC 自动选择,camelCase ↔ snake_case 自动转换)
|
||||
│ │ ├── generated/ # OpenAPI 生成的 TypeScript 类型
|
||||
│ │ ├── client.ts # HTTP 客户端(camelCase ↔ snake_case 自动转换)
|
||||
│ │ └── modules/ # 按领域拆分的 API 模块
|
||||
│ ├── components/ # 可复用组件(PascalCase 文件夹)
|
||||
│ ├── pages/ # 页面级组件(PascalCase 文件夹)
|
||||
│ ├── store/ # Zustand 状态管理(含 __tests__)
|
||||
│ ├── store/ # Zustand 状态管理
|
||||
│ ├── hooks/ # 自定义 React Hooks
|
||||
│ ├── utils/ # 工具函数
|
||||
│ ├── styles/ # CSS 变量与全局样式
|
||||
@@ -97,11 +96,8 @@ tauri-app/
|
||||
│ │ ├── lib.rs # Tauri Builder、Command 定义、公共类型
|
||||
│ │ ├── ffmpeg_cmd.rs # FFmpeg 命令封装
|
||||
│ │ ├── video_processing.rs # 压制成片业务逻辑
|
||||
│ │ ├── api_proxy.rs # Python API 代理
|
||||
│ │ ├── auth.rs # 认证命令
|
||||
│ │ ├── avatar_cache.rs # 头像缓存
|
||||
│ │ ├── storage/ # 本地存储引擎(项目、认证、配置、头像等)
|
||||
│ │ ├── commands/ # Tauri IPC 命令(按领域拆分)
|
||||
│ │ ├── commands/ # Tauri IPC 命令(按领域拆分:asset, auth_state, cover_avatar, file, product, project, video_compose, voice 等)
|
||||
│ │ └── utils.rs # 通用工具
|
||||
│ ├── Cargo.toml # Rust 依赖
|
||||
│ ├── tauri.conf.json # Tauri 应用配置(窗口、CSP、打包、sidecar)
|
||||
@@ -231,8 +227,7 @@ npm run format:check # Prettier --check
|
||||
npm run stylelint # Stylelint
|
||||
npm run stylelint:fix # Stylelint --fix
|
||||
|
||||
# OpenAPI 类型生成
|
||||
npm run gen:api # 根据 openapi.json 生成 TypeScript 类型
|
||||
# 注:当前项目未配置 OpenAPI 自动生成 TypeScript 类型的脚本
|
||||
```
|
||||
|
||||
---
|
||||
@@ -280,7 +275,7 @@ npm run gen:api # 根据 openapi.json 生成 TypeScript 类型
|
||||
|
||||
1. **判断是否需要本地能力**(FFmpeg、文件系统、系统调用)。
|
||||
2. **不需要** → 直接在 `tauri-app/src/api/modules/` 使用 `client.get/post/put/delete` 调用 Python HTTP API。
|
||||
3. **需要** → 将 endpoint 加入 `tauri-app/src/api/client.ts` 的 IPC 处理逻辑,并在 `tauri-app/src-tauri/src/commands/` 或 `lib.rs` 中实现对应的 `#[tauri::command]` 处理器。
|
||||
3. **需要** → 在 `tauri-app/src/api/modules/` 中通过 `@tauri-apps/api/core` 的 `invoke` 调用 Rust 命令,并在 `tauri-app/src-tauri/src/commands/` 或 `lib.rs` 中实现对应的 `#[tauri::command]` 处理器。
|
||||
|
||||
### 语义层防护网(后端)
|
||||
|
||||
@@ -304,7 +299,6 @@ Makefile 中 `lint-semantic` 目标会检查以下规则:
|
||||
- **组件测试**: `@testing-library/react` + `@testing-library/jest-dom`
|
||||
- **文件位置**:
|
||||
- 全局 setup: `src/__tests__/setup.ts`
|
||||
- Store 测试: `src/store/__tests__/*.test.tsx`
|
||||
- 组件/页面测试: 建议放在被测文件同目录或 `__tests__` 子目录中
|
||||
- **Mock 策略**: `setup.ts` 中已全局 mock `localStorage`、`@tauri-apps/api/core` 的 `invoke` 方法、`window.__TAURI_INTERNALS__`。每个测试后自动调用 `vi.clearAllMocks()`。
|
||||
|
||||
@@ -327,13 +321,11 @@ Makefile 中 `lint-semantic` 目标会检查以下规则:
|
||||
|
||||
### 部署流程
|
||||
|
||||
#### 测试环境(GitLab CI)
|
||||
#### 测试环境(GitHub Actions)
|
||||
|
||||
`.gitlab-ci.yml` 定义了 `deploy-backend` 任务:
|
||||
1. 在部署服务器拉取代码(`master` 分支触发)。
|
||||
2. 构建 api + scheduler 镜像(`docker-compose.test.yml`)。
|
||||
3. 启动服务,健康检查 `curl http://localhost:8081/health`。
|
||||
4. 清理 7 天前的旧镜像。
|
||||
`.github/workflows/` 存放 CI/CD 工作流:
|
||||
- `release.yml`:Tauri 桌面端 Release 打包工作流(按 tag 触发,支持 macOS / Windows 平台及 sidecar 二进制下载)。
|
||||
- 后端 api + scheduler 的测试/生产部署目前通过手动执行 `docker-compose.test.yml` / `docker-compose.prod.yml` 完成。
|
||||
|
||||
#### 生产环境
|
||||
|
||||
@@ -384,7 +376,7 @@ Makefile 中 `lint-semantic` 目标会检查以下规则:
|
||||
- **ORM**: SQLAlchemy 2.0(异步,asyncpg 驱动)
|
||||
- **迁移工具**: Alembic
|
||||
- **基础模型**: `app.models.base.BaseModel` 提供 UUID 主键、`created_at`、`updated_at`
|
||||
- **当前模型**: `User`(用户/设备认证)
|
||||
- **当前模型**: 包括 `User`(用户/设备认证)、`UserDevice`、`UserPoint`、`PointRechargeOrder`、`PointTransaction`、`BrollCategory`、`BrollMaterial`、`BrollTag`、`CoverBackground`、`BgmMusic`、`Update` 等
|
||||
- **迁移注意**: Alembic 使用同步连接(psycopg2),会自动将 `+asyncpg` 替换掉。
|
||||
|
||||
---
|
||||
|
||||
+100
-51
@@ -197,11 +197,13 @@ ON CONFLICT (version) DO NOTHING;
|
||||
| 方法 | 路径 | 说明 | 认证 |
|
||||
|------|------|------|------|
|
||||
| POST | `/api/v1/update/check` | 检查应用更新 | 无需认证 |
|
||||
| GET | `/api/v1/update/download/{version}/{platform}` | 获取下载 URL 并记录 | 无需认证 |
|
||||
| GET | `/api/v1/update/download` | 统一下载入口:自动匹配最新版本和平台安装包 | 无需认证 |
|
||||
| POST | `/api/v1/update/releases` | 创建新版本发布 | 需要管理员认证 |
|
||||
| GET | `/api/v1/update/releases` | 获取所有版本列表 | 需要管理员认证 |
|
||||
| DELETE | `/api/v1/update/releases/{version}` | 删除版本发布 | 需要管理员认证 |
|
||||
|
||||
> 说明:`/download` 优先根据 `User-Agent` 识别平台(darwin / windows / linux)和架构(x86_64 / aarch64),也支持通过查询参数显式指定,例如 `?target=darwin&arch=aarch64`。返回 302 重定向到七牛云上的对应安装包。
|
||||
|
||||
### 3.2 数据模型
|
||||
|
||||
#### 3.2.1 SQLAlchemy 模型
|
||||
@@ -350,9 +352,10 @@ class DownloadResponse(BaseModel):
|
||||
文件位置:`python-api/app/api/v1/update.py`
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, Query, Request, status
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, and_
|
||||
from sqlalchemy import select
|
||||
from typing import Optional
|
||||
|
||||
from ...deps import get_db
|
||||
@@ -443,69 +446,115 @@ async def check_update(
|
||||
]
|
||||
)
|
||||
|
||||
@router.get("/download/{version}/{platform}", response_model=DownloadResponse)
|
||||
async def get_download_url(
|
||||
version: str,
|
||||
platform: str,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
@router.get("/download")
|
||||
async def download_latest(
|
||||
request: Request,
|
||||
target: str | None = Query(None, description="平台:darwin / windows / linux"),
|
||||
arch: str | None = Query(None, description="架构:x86_64 / aarch64 / i686"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
获取下载 URL 并记录下载日志
|
||||
|
||||
Args:
|
||||
version: 目标版本
|
||||
platform: 平台类型
|
||||
|
||||
Returns:
|
||||
包含下载 URL、文件大小和哈希的响应
|
||||
统一下载入口:自动匹配最新版本和当前环境安装包。
|
||||
|
||||
优先级:
|
||||
1. 查询参数 `target` + `arch`(最可靠,推荐应用内使用)
|
||||
2. `User-Agent` 解析(兜底,适合网页/文档中的固定链接)
|
||||
|
||||
匹配规则:
|
||||
- 返回 302 重定向到七牛云上的安装包地址
|
||||
- 优先返回用户安装包(`.dmg` / `.exe` / `.msi` / `.AppImage`)
|
||||
- 其次返回 updater 用的 `.app.tar.gz`
|
||||
- 同一平台若找不到精确架构,会兜底返回同平台的其他架构包
|
||||
"""
|
||||
# 查询版本信息
|
||||
# 1. 确定平台与架构
|
||||
if target and arch:
|
||||
platform = target.lower()
|
||||
architecture = arch.lower()
|
||||
else:
|
||||
parsed = _parse_user_agent(request.headers.get("user-agent"))
|
||||
if not parsed:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="无法识别您的操作系统,请通过官网或应用商店下载对应版本",
|
||||
)
|
||||
platform, architecture = parsed
|
||||
|
||||
# 2. 查询最新版本
|
||||
result = await db.execute(
|
||||
select(AppRelease).where(AppRelease.version == version)
|
||||
select(AppRelease).order_by(AppRelease.release_date.desc()).limit(1)
|
||||
)
|
||||
release = result.scalar_one_or_none()
|
||||
|
||||
if not release:
|
||||
latest: AppRelease | None = result.scalar_one_or_none()
|
||||
if not latest:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Release not found"
|
||||
detail="暂无可用下载",
|
||||
)
|
||||
|
||||
# 查询对应平台的包
|
||||
|
||||
# 3. 查询该平台所有包(macOS 常用 universal 包会同时写入 x86_64/aarch64)
|
||||
result = await db.execute(
|
||||
select(ReleasePackage).where(
|
||||
and_(
|
||||
ReleasePackage.release_id == release.id,
|
||||
ReleasePackage.platform == platform
|
||||
)
|
||||
ReleasePackage.release_id == latest.id,
|
||||
ReleasePackage.platform == platform,
|
||||
)
|
||||
)
|
||||
package = result.scalar_one_or_none()
|
||||
|
||||
if not package:
|
||||
platform_pkgs = list(result.scalars().all())
|
||||
|
||||
if not platform_pkgs:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Package not found for platform {platform}"
|
||||
detail=f"版本 {latest.version} 暂无可用的 {platform} 安装包",
|
||||
)
|
||||
|
||||
# 增加下载计数
|
||||
package.download_count += 1
|
||||
|
||||
# 记录下载日志(可选,不阻塞主流程)
|
||||
download_log = UpdateDownload(
|
||||
release_id=release.id,
|
||||
platform=platform,
|
||||
app_version=version
|
||||
)
|
||||
db.add(download_log)
|
||||
|
||||
await db.commit()
|
||||
|
||||
return DownloadResponse(
|
||||
download_url=package.file_url,
|
||||
file_size=package.file_size,
|
||||
file_hash=package.file_hash
|
||||
)
|
||||
|
||||
# 4. 优先选择用户安装包,而不是 updater 用的 .app.tar.gz
|
||||
def _install_pkg_priority(pkg: ReleasePackage) -> int:
|
||||
name = pkg.filename.lower()
|
||||
if name.endswith(".dmg"):
|
||||
return 1
|
||||
if name.endswith(".exe"):
|
||||
return 2
|
||||
if name.endswith(".msi"):
|
||||
return 3
|
||||
if name.endswith(".appimage"):
|
||||
return 4
|
||||
if name.endswith(".app.tar.gz"):
|
||||
return 10
|
||||
return 5
|
||||
|
||||
exact_arch_pkgs = [p for p in platform_pkgs if p.architecture == architecture]
|
||||
candidate_pkgs = exact_arch_pkgs or platform_pkgs
|
||||
package = min(candidate_pkgs, key=_install_pkg_priority)
|
||||
|
||||
return RedirectResponse(url=package.file_url)
|
||||
|
||||
|
||||
def _parse_user_agent(user_agent: str | None) -> tuple[str, str] | None:
|
||||
"""从 User-Agent 解析 Tauri 平台标识和架构。"""
|
||||
if not user_agent:
|
||||
return None
|
||||
|
||||
ua = user_agent.lower()
|
||||
|
||||
if "windows" in ua:
|
||||
platform = "windows"
|
||||
arch = "aarch64" if "arm64" in ua or "aarch64" in ua else "x86_64"
|
||||
return platform, arch
|
||||
|
||||
if "macintosh" in ua or "mac os x" in ua:
|
||||
platform = "darwin"
|
||||
if "arm64" in ua or "aarch64" in ua:
|
||||
arch = "aarch64"
|
||||
elif "intel" in ua:
|
||||
arch = "x86_64"
|
||||
else:
|
||||
arch = "aarch64"
|
||||
return platform, arch
|
||||
|
||||
if "linux" in ua:
|
||||
platform = "linux"
|
||||
arch = "aarch64" if "aarch64" in ua or "arm64" in ua else "x86_64"
|
||||
return platform, arch
|
||||
|
||||
return None
|
||||
|
||||
@router.post("/releases", response_model=ReleaseResponse)
|
||||
async def create_release(
|
||||
|
||||
+52
-13
@@ -7,14 +7,20 @@
|
||||
|
||||
## 前置条件
|
||||
|
||||
### 1. 签名密钥(已生成,只需确认存在)
|
||||
### 1. 签名密钥
|
||||
|
||||
当前使用 Tauri 自动更新签名密钥对,私钥用于构建时签名,公钥写入前端配置。
|
||||
|
||||
```bash
|
||||
# 确认密钥对存在(私钥文件名以你本地实际为准)
|
||||
ls ~/.tauri/meijiaka.key ~/.tauri/meijiaka.key.pub
|
||||
```
|
||||
|
||||
- 私钥 `~/.tauri/meijiaka.key`:构建时用于签名,**不要泄露**
|
||||
- 公钥内容:已写入 `tauri-app/src-tauri/tauri.conf.json` 的 `plugins.updater.pubkey`
|
||||
- **私钥**:构建时用于签名更新包,**不要泄露,不要提交到 Git**
|
||||
- **公钥**:内容已写入 `tauri-app/src-tauri/tauri.conf.json` 的 `plugins.updater.pubkey`
|
||||
|
||||
> **注意**:如果重新生成了签名密钥对,旧版本客户端将无法通过自动更新升级(旧公钥无法验证新私钥的签名),只能手动下载重装。详细说明见本文档末尾"密钥更换与手动下载"。
|
||||
|
||||
|
||||
### 2. 七牛云环境变量(复用素材上传配置)
|
||||
|
||||
@@ -45,26 +51,34 @@ curl https://dev.tapi.meijiaka.cn/api/v1/system/health
|
||||
|
||||
### 步骤 1:修改版本号
|
||||
|
||||
三个文件版本号必须完全一致:
|
||||
所有包含版本号的位置必须保持一致,建议统一修改后全局搜索确认:
|
||||
|
||||
```bash
|
||||
cd tauri-app
|
||||
# 项目根目录
|
||||
VERSION
|
||||
AGENTS.md
|
||||
|
||||
# 1. package.json
|
||||
npm version 1.6.0 --no-git-tag-version
|
||||
# 前端
|
||||
tauri-app/package.json
|
||||
tauri-app/src-tauri/Cargo.toml
|
||||
tauri-app/src-tauri/tauri.conf.json
|
||||
tauri-app/src-tauri/Cargo.lock # name = "tauri-app" 对应的 version
|
||||
tauri-app/AGENTS.md
|
||||
|
||||
# 2. Cargo.toml
|
||||
# 手动修改:src-tauri/Cargo.toml → version = "1.6.0"
|
||||
|
||||
# 3. tauri.conf.json
|
||||
# 手动修改:src-tauri/tauri.conf.json → "version": "1.6.0"
|
||||
# 后端
|
||||
python-api/pyproject.toml
|
||||
python-api/uv.lock # name = "meijiaka-ai-api" 对应的 version
|
||||
python-api/app/config.py # APP_VERSION 默认值
|
||||
```
|
||||
|
||||
> 当前版本示例:`1.9.1`。修改后可用 `grep -R "1.9.0"` 检查是否有遗漏。
|
||||
|
||||
### 步骤 2:构建
|
||||
|
||||
```bash
|
||||
cd tauri-app
|
||||
export TAURI_SIGNING_PRIVATE_KEY="$HOME/.tauri/meijiaka.key"
|
||||
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" # 若私钥有密码则填写
|
||||
npm run tauri build
|
||||
```
|
||||
|
||||
@@ -162,12 +176,37 @@ Tauri updater 插件已内置跨平台安装逻辑,前端代码无需区分平
|
||||
|
||||
---
|
||||
|
||||
## 密钥更换与手动下载
|
||||
|
||||
如果签名密钥对发生更换(例如旧私钥丢失、泄露或主动轮换):
|
||||
|
||||
1. **旧版本客户端无法自动更新**
|
||||
- 旧客户端内置的旧公钥无法验证新私钥签名的更新包
|
||||
- Tauri updater 会在签名验证阶段失败
|
||||
|
||||
2. **必须引导用户手动下载重装**
|
||||
- 后端已提供统一下载入口:`GET /api/v1/update/download`
|
||||
- 该接口根据 `User-Agent` 自动匹配最新版本和平台安装包
|
||||
- 也支持显式传参:`/api/v1/update/download?target=darwin&arch=x86_64`
|
||||
- 返回 **302 重定向**到对应安装包的七牛云 URL
|
||||
|
||||
3. **分发链接示例**
|
||||
- 网页/文档固定链接:`https://dev.tapi.meijiaka.cn/api/v1/update/download`
|
||||
- 应用内手动下载按钮:调用 Tauri `opener` 打开上述链接即可
|
||||
|
||||
4. **恢复自动更新**
|
||||
- 用户手动安装新版本后,新安装包中已包含新公钥
|
||||
- 后续版本可恢复正常的自动更新流程
|
||||
|
||||
---
|
||||
|
||||
## 文件清单
|
||||
|
||||
| 文件 | 作用 |
|
||||
|------|------|
|
||||
| `~/.tauri/meijiaka.key` | 私钥(签名用,勿泄露) |
|
||||
| `tauri-app/.tauri-signing-key.pub` | 公钥源文件 |
|
||||
| `tauri-app/src-tauri/tauri.conf.json` | updater 配置:公钥 + endpoint URL |
|
||||
| `python-api/scripts/publish_release.py` | 发版脚本(扫描 .sig → 上传七牛云 → 写数据库) |
|
||||
| `python-api/app/api/v1/update.py` | 后端更新检查 API |
|
||||
| `python-api/app/api/v1/update.py` | 后端更新检查 API + 统一下载入口 |
|
||||
| `python-api/app/models/update.py` | 数据库模型(`mjk_app_releases` / `mjk_app_release_packages`) |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# === 基础配置 ===
|
||||
APP_NAME=美家卡智影 API
|
||||
APP_VERSION=1.8.0
|
||||
APP_VERSION=1.8.2
|
||||
# ⚠️ 生产环境必须设为 false
|
||||
DEBUG=true
|
||||
ENV=development
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"http:Pn60lJXcaOGKvMjn5qv-OMr7wR1lp1p8QG7Ul6NK:media-liche": {"upHosts": ["http://upload-z2.qiniup.com", "http://up-z2.qiniup.com"], "ioHosts": ["http://iovip-z2.qbox.me"], "rsHosts": ["http://rs-z2.qbox.me"], "rsfHosts": ["http://rsf-z2.qbox.me"], "apiHosts": ["http://api-z2.qiniu.com"], "deadline": 1780541956}, "http:Pn60lJXcaOGKvMjn5qv-OMr7wR1lp1p8QG7Ul6NK:img-liche": {"upHosts": ["http://upload-z2.qiniup.com", "http://up-z2.qiniup.com"], "ioHosts": ["http://iovip-z2.qbox.me"], "rsHosts": ["http://rs-z2.qbox.me"], "rsfHosts": ["http://rsf-z2.qbox.me"], "apiHosts": ["http://api-z2.qiniu.com"], "deadline": 1776433218}}
|
||||
+11
-17
@@ -115,26 +115,20 @@ lint-semantic: ## 语义层禁词检查(防止供应商术语泄漏到业务
|
||||
echo "❌ API 层发现 element_id(应使用 provider_element_id 或 human_id)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@# Scheduler 层禁止 task_id 作为内部变量/Redis key(读取 Provider 返回除外)
|
||||
@errs=$$(grep -rn '\btask_id\b' app/scheduler --include='*.py' \
|
||||
| grep -v 'job_id' \
|
||||
| grep -v '__pycache__' \
|
||||
| grep -v '\.get("task_id")' \
|
||||
| grep -v 'result.get("task_id")' \
|
||||
| grep -v 'task_type' \
|
||||
| grep -v '"task_id"' \
|
||||
| grep -v "'task_id'"); \
|
||||
if [ -n "$$errs" ]; then \
|
||||
echo "$$errs"; \
|
||||
echo "❌ Scheduler 层发现 task_id(应使用 job_id)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@# Scheduler 层 Redis key 必须使用 job: 而非 task:
|
||||
@errs=$$(grep -rn 'redis.*task:' app/scheduler --include='*.py' \
|
||||
@# Scheduler 层统一使用 task 命名,禁止混用 job
|
||||
@errs=$$(grep -rn '\bjob_id\b' app/scheduler --include='*.py' \
|
||||
| grep -v '__pycache__'); \
|
||||
if [ -n "$$errs" ]; then \
|
||||
echo "$$errs"; \
|
||||
echo "❌ Scheduler Redis key 使用 task:(应使用 job:)"; \
|
||||
echo "❌ Scheduler 层发现 job_id(应使用 task_id)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@# Scheduler 层 Redis key 必须使用 task: 而非 job:
|
||||
@errs=$$(grep -rn 'redis.*job:' app/scheduler --include='*.py' \
|
||||
| grep -v '__pycache__'); \
|
||||
if [ -n "$$errs" ]; then \
|
||||
echo "$$errs"; \
|
||||
echo "❌ Scheduler Redis key 使用 job:(应使用 task:)"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "✅ 语义层检查通过"
|
||||
|
||||
@@ -113,7 +113,7 @@ class ViduAdapter(PlatformAdapter, SyncCapable, TaskCapable, CallbackCapable):
|
||||
result = await self.provider.clone_voice(
|
||||
audio_url=payload["audio_url"],
|
||||
voice_id=payload["voice_id"],
|
||||
text=payload.get("text"),
|
||||
text=payload.get("text") or "",
|
||||
)
|
||||
return AdapterResponse(
|
||||
success=True,
|
||||
@@ -219,6 +219,7 @@ class ViduAdapter(PlatformAdapter, SyncCapable, TaskCapable, CallbackCapable):
|
||||
) -> bool:
|
||||
"""验证 Vidu 回调 HMAC-SHA256 签名"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# HTTP 头大小写不敏感:建立小写 key 的查找表
|
||||
@@ -233,6 +234,9 @@ class ViduAdapter(PlatformAdapter, SyncCapable, TaskCapable, CallbackCapable):
|
||||
if not all([signature, algorithm, access_key, signed_headers_str, date]):
|
||||
logger.warning(f"[Vidu] 签名验证失败: 缺少必要头, headers={list(headers.keys())}")
|
||||
return False
|
||||
assert signature is not None
|
||||
assert signed_headers_str is not None
|
||||
assert date is not None
|
||||
if algorithm != "hmac-sha256":
|
||||
logger.warning(f"[Vidu] 签名验证失败: 不支持的算法 {algorithm}")
|
||||
return False
|
||||
@@ -256,17 +260,15 @@ class ViduAdapter(PlatformAdapter, SyncCapable, TaskCapable, CallbackCapable):
|
||||
canonical_query_string = parsed.query or ""
|
||||
|
||||
signing_string = (
|
||||
f"POST\n"
|
||||
f"{http_uri}\n"
|
||||
f"{canonical_query_string}\n"
|
||||
f"vidu\n"
|
||||
f"{date}\n"
|
||||
f"POST\n" f"{http_uri}\n" f"{canonical_query_string}\n" f"vidu\n" f"{date}\n"
|
||||
)
|
||||
for name in header_names:
|
||||
signing_string += f"{name}:{header_values[name]}\n"
|
||||
|
||||
expected = base64.b64encode(
|
||||
hmac.new(secret.encode("utf-8"), signing_string.encode("utf-8"), hashlib.sha256).digest()
|
||||
hmac.new(
|
||||
secret.encode("utf-8"), signing_string.encode("utf-8"), hashlib.sha256
|
||||
).digest()
|
||||
).decode("utf-8")
|
||||
|
||||
if not hmac.compare_digest(signature, expected):
|
||||
@@ -307,6 +309,12 @@ class ViduAdapter(PlatformAdapter, SyncCapable, TaskCapable, CallbackCapable):
|
||||
|
||||
return TaskStatus(
|
||||
state=self.normalize_state(state),
|
||||
result={"video_url": video_url, "creations": creations, "task_id": task_id} if video_url else {"task_id": task_id},
|
||||
error_message=(data.get("err_code") or data.get("message")) if state == "failed" else None,
|
||||
result=(
|
||||
{"video_url": video_url, "creations": creations, "task_id": task_id}
|
||||
if video_url
|
||||
else {"task_id": task_id}
|
||||
),
|
||||
error_message=(
|
||||
(data.get("err_code") or data.get("message")) if state == "failed" else None
|
||||
),
|
||||
)
|
||||
|
||||
@@ -69,11 +69,11 @@ class VolcengineArkAdapter(PlatformAdapter, SyncCapable):
|
||||
)
|
||||
|
||||
elif method == Method.EMBEDDING:
|
||||
result = await self.provider.create_embeddings(
|
||||
embedding_result: dict[str, Any] = await self.provider.create_embeddings(
|
||||
texts=payload["texts"],
|
||||
model=payload.get("model"),
|
||||
)
|
||||
return AdapterResponse(success=True, data=result)
|
||||
return AdapterResponse(success=True, data=embedding_result)
|
||||
|
||||
else:
|
||||
return AdapterResponse(
|
||||
|
||||
@@ -24,7 +24,9 @@ logger = logging.getLogger(__name__)
|
||||
class LLMGateway:
|
||||
"""LLM 调用网关"""
|
||||
|
||||
def __init__(self, adapters: dict[str, SyncCapable], fallback_chains: dict[str, list[str]] | None = None):
|
||||
def __init__(
|
||||
self, adapters: dict[str, SyncCapable], fallback_chains: dict[str, list[str]] | None = None
|
||||
):
|
||||
self.adapters = adapters
|
||||
self.fallback_chains = fallback_chains or {}
|
||||
|
||||
@@ -55,15 +57,18 @@ class LLMGateway:
|
||||
for mid in models_to_try:
|
||||
adapter = self._get_adapter(platform)
|
||||
try:
|
||||
result = await adapter.call(Method.CHAT, {
|
||||
"prompt": prompt,
|
||||
"model": mid,
|
||||
**kwargs,
|
||||
})
|
||||
result = await adapter.call(
|
||||
Method.CHAT,
|
||||
{
|
||||
"prompt": prompt,
|
||||
"model": mid,
|
||||
**kwargs,
|
||||
},
|
||||
)
|
||||
if result.success:
|
||||
if mid != model_id:
|
||||
logger.warning(f"[LLMGateway] 模型降级成功: {model_id} → {mid}")
|
||||
return result.data
|
||||
return result.data or {}
|
||||
else:
|
||||
last_error = PlatformError(
|
||||
result.error_message or f"模型 {mid} 调用失败",
|
||||
@@ -82,6 +87,3 @@ class LLMGateway:
|
||||
platform=platform,
|
||||
retryable=False,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from app.ai.adapters.constants import Method
|
||||
from app.ai.providers.base import GenerationResult, ModelHealth, ProviderError
|
||||
from app.ai.providers.volcengine_provider import VolcengineProvider
|
||||
from app.core.config_loader import AIModelConfigLoader, get_config_loader
|
||||
from app.core.exceptions import AppException, PlatformError
|
||||
from app.platform_gateway import PlatformGateway
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -26,9 +27,7 @@ class _PlatformInstance:
|
||||
self.gateway = gateway
|
||||
self.provider_id = config.get("id", "")
|
||||
|
||||
async def generate(
|
||||
self, model_name: str, prompt: str, **kwargs
|
||||
) -> GenerationResult:
|
||||
async def generate(self, model_name: str, prompt: str, **kwargs) -> GenerationResult:
|
||||
"""调用生成(通过 PlatformGateway)"""
|
||||
if self.gateway:
|
||||
result = await self.gateway.call_sync(
|
||||
@@ -41,9 +40,7 @@ class _PlatformInstance:
|
||||
},
|
||||
)
|
||||
if not result.success:
|
||||
raise ProviderError(
|
||||
result.error_message or f"{self.provider_id} 调用失败"
|
||||
)
|
||||
raise ProviderError(result.error_message or f"{self.provider_id} 调用失败")
|
||||
data = result.data or {}
|
||||
return GenerationResult(
|
||||
content=data.get("content", ""),
|
||||
@@ -64,7 +61,11 @@ class _PlatformInstance:
|
||||
id=model_name or self.provider_id,
|
||||
name=self.provider_id,
|
||||
is_available=adapter_result.success,
|
||||
response_time=adapter_result.data.get("response_time_ms", 0) if adapter_result.data else 0,
|
||||
response_time=(
|
||||
adapter_result.data.get("response_time_ms", 0)
|
||||
if adapter_result.data
|
||||
else 0
|
||||
),
|
||||
last_error=adapter_result.error_message,
|
||||
)
|
||||
except Exception as e:
|
||||
@@ -89,7 +90,6 @@ class ModelRouter:
|
||||
- 模型自动选择
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.platforms: dict[str, _PlatformInstance] = {}
|
||||
self._config_loader: AIModelConfigLoader | None = None
|
||||
@@ -249,11 +249,7 @@ class ModelRouter:
|
||||
if task_type:
|
||||
model_id = self.select_model_for_task(task_type)
|
||||
if model_id is None:
|
||||
models = (
|
||||
self._config_loader.get_enabled_models()
|
||||
if self._config_loader
|
||||
else []
|
||||
)
|
||||
models = self._config_loader.get_enabled_models() if self._config_loader else []
|
||||
if models:
|
||||
model_id = models[0].id
|
||||
else:
|
||||
@@ -270,9 +266,9 @@ class ModelRouter:
|
||||
params = {**model.default_params, **kwargs}
|
||||
|
||||
try:
|
||||
return await platform.generate(
|
||||
prompt=prompt, model_name=model.model_name, **params
|
||||
)
|
||||
return await platform.generate(prompt=prompt, model_name=model.model_name, **params)
|
||||
except (PlatformError, AppException):
|
||||
raise
|
||||
except Exception as e:
|
||||
raise ProviderError(f"模型 {model_id} 生成失败: {e}") from e
|
||||
|
||||
@@ -290,7 +286,11 @@ class ModelRouter:
|
||||
id=model.id,
|
||||
name=model.display_name,
|
||||
is_available=adapter_result.success,
|
||||
response_time=adapter_result.data.get("response_time_ms", 0) if adapter_result.data else 0,
|
||||
response_time=(
|
||||
adapter_result.data.get("response_time_ms", 0)
|
||||
if adapter_result.data
|
||||
else 0
|
||||
),
|
||||
last_error=adapter_result.error_message,
|
||||
)
|
||||
else:
|
||||
@@ -306,11 +306,12 @@ class ModelRouter:
|
||||
# fallback: 直接通过 PlatformInstance
|
||||
results = {}
|
||||
if model_id:
|
||||
model = self._config_loader.get_model(model_id) if self._config_loader else None
|
||||
if model:
|
||||
platform = self.platforms.get(model.platform_id)
|
||||
if platform:
|
||||
results[model_id] = await platform.health_check(model.model_name)
|
||||
target_model = self._config_loader.get_model(model_id) if self._config_loader else None
|
||||
if target_model is None:
|
||||
raise ProviderError(f"模型不存在: {model_id}")
|
||||
platform = self.platforms.get(target_model.platform_id)
|
||||
if platform:
|
||||
results[model_id] = await platform.health_check(target_model.model_name)
|
||||
else:
|
||||
if self._config_loader:
|
||||
for model in self._config_loader.get_enabled_models():
|
||||
|
||||
@@ -94,10 +94,12 @@ def list_categories() -> list[dict]:
|
||||
for cat_meta in meta.get("categories", []):
|
||||
cat_code = cat_meta["code"]
|
||||
cat_name = cat_meta.get("name", cat_code)
|
||||
categories.append({
|
||||
"code": cat_code,
|
||||
"name": cat_name,
|
||||
})
|
||||
categories.append(
|
||||
{
|
||||
"code": cat_code,
|
||||
"name": cat_name,
|
||||
}
|
||||
)
|
||||
|
||||
return categories
|
||||
|
||||
@@ -135,11 +137,13 @@ def list_prompt_files(category: str) -> list[dict]:
|
||||
else:
|
||||
label = name
|
||||
desc = ""
|
||||
files.append({
|
||||
"filename": f.name,
|
||||
"label": label.strip(),
|
||||
"desc": desc.strip(),
|
||||
})
|
||||
files.append(
|
||||
{
|
||||
"filename": f.name,
|
||||
"label": label.strip(),
|
||||
"desc": desc.strip(),
|
||||
}
|
||||
)
|
||||
|
||||
return files
|
||||
|
||||
@@ -174,7 +178,6 @@ def load_system_prompt(category: str, subcategory: str) -> str:
|
||||
return load_prompt_file(category, chosen["filename"])
|
||||
|
||||
|
||||
|
||||
def load_script_user_prompt(
|
||||
topic: str,
|
||||
extra_params: str | None = None,
|
||||
|
||||
@@ -1,244 +1,99 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修不懂各工序停工养护时长、盲目赶工期容易留下装修隐患的业主,围绕装修七大工序标准停工等待时间创作,按原文顺序排列,不打乱不随机调整。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,无多余开头、无结尾引导,直接进入正文干货内容,简洁直白适配短平快口播。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
无专属开头范式,去掉所有引入铺垫话术,直接进入正文工序停工时长内容。
|
||||
中间核心(七大装修工序停工时长内容,文案可微调句式口语化,保持原意不变,严格按原文顺序不打乱):
|
||||
砌墙施工完成后,必须停工等待 5 天再进行下一道工序。
|
||||
水电工程完工后,固定停工两天静置养护。
|
||||
全屋防水涂料涂刷完毕,需要停工静置 3 天。
|
||||
瓷砖全部铺贴完成后,静置停工等待 5 天。
|
||||
美缝施工结束后,停工两天自然干透固化。
|
||||
墙面腻子刮涂完成,停工静置养护 3 天。
|
||||
全屋乳胶漆涂刷完工,至少停工通风静置 7 天。
|
||||
中间核心详细分析(贴合口播逻辑,不篡改原文核心)
|
||||
排序逻辑:严格照搬原文七大工序先后顺序,不打乱、不随机重排,贴合装修施工真实流程,条理清晰一目了然。
|
||||
文案调整要求:仅做口语化精简微调,保留每道工序名称、停工天数全部核心信息,不增减内容、不改变原意,适配短视频短促口播风格。
|
||||
字数与时长控制:纯文字 + 数字扣除标点,严格控制在 60-80 字,按每秒 4 字核算,对应时长 15-20s,内容精炼简短、节奏紧凑。
|
||||
内容适配性:纯干货直给,无多余废话,每句对应一道工序标准停工时长,适合做知识点短句口播,记忆点强、实用性高。
|
||||
结尾范式:无额外结尾话术,正文内容结束即收尾,不添加福利引导、不额外延伸。
|
||||
【开篇 & 语言要求】
|
||||
无开篇引入,直接切入正文知识点;全程短句口语化,直白易懂、干练简洁,只播报核心工序与停工天数,不做多余解释说教。
|
||||
可微调句式语序,严禁改动工序顺序、停工天数、施工节点核心内容,语句简短利落,适配短时长口播节奏。
|
||||
【内置固定原文案】
|
||||
砌墙结束之后,要停工 5 天。
|
||||
水电完工之后,要停工两天。
|
||||
防水刷完之后,要停工 3 天。
|
||||
瓷砖贴完之后,要停工 5 天。
|
||||
美缝做完之后,要停工两天。
|
||||
腻子刮完之后,要停工 3 天。
|
||||
乳胶漆刷完之后,要停工 7 天。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为: 一段人物出镜
|
||||
其他都是空镜补充
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "新建墙体垂直找平 - 新建砌筑",
|
||||
"voiceover": "砌墙完工之后,一定要停工静置等待 5 天。",
|
||||
"duration": "4.25s"
|
||||
}
|
||||
]
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
你的任务是生成装修避坑口播文案,必须严格遵守以下所有规则,不得有任何偏差:
|
||||
|
||||
1. 固定开头:第一行意思【装修这几个时间点必须停工】,文案可微调句式口语化,保持原意不变
|
||||
2. 固定结尾:最后一行必须是【关注我,装修不踩坑】
|
||||
3. 中间内容:根据下面给出的七个装修停工时间点,文案可微调句式口语化,保持原意不变,严格按原文顺序不打乱
|
||||
4. 格式要求:每组单独成行,格式为先讲工序,再讲时间
|
||||
|
||||
以下是七大装修工序停工时长内容,文案可微调句式口语化,保持原意不变,严格按原文顺序不打乱:
|
||||
砌墙施工完成后,必须停工等待 5 天再进行下一道工序。
|
||||
水电工程完工后,固定停工两天静置养护。
|
||||
全屋防水涂料涂刷完毕,需要停工静置 3 天。
|
||||
瓷砖全部铺贴完成后,静置停工等待 5 天。
|
||||
美缝施工结束后,停工两天自然干透固化。
|
||||
墙面腻子刮涂完成,停工静置养护 3 天。
|
||||
全屋乳胶漆涂刷完工,至少停工通风静置 7 天。
|
||||
中间核心详细分析(贴合口播逻辑,不篡改原文核心,格式严格为"先讲工序,再讲停工几天")
|
||||
排序逻辑:严格照搬原文七大工序先后顺序,不打乱、不随机重排,贴合装修施工真实流程,条理清晰一目了然。
|
||||
文案调整要求:仅做口语化调整,保留每道工序名称、停工天数全部核心信息,不增减内容、不改变原意,适配短视频短促口播风格。
|
||||
字数与时长控制:纯文字 + 数字扣除标点,按每秒 4 字核算。
|
||||
内容适配性:纯干货直给,无多余废话,每句对应一道工序标准停工时长,适合做知识点短句口播,记忆点强、实用性高。
|
||||
结尾范式:无额外结尾话术,正文内容结束即收尾,不添加福利引导、不额外延伸。
|
||||
【开篇 & 语言要求】
|
||||
无开篇引入,直接切入正文知识点;全程短句口语化,直白易懂、干练简洁,只播报核心工序与停工天数,不做多余解释说教。
|
||||
可微调句式语序,严禁改动工序顺序、停工天数、施工节点核心内容,语句简短利落,适配短时长口播节奏。
|
||||
【内置固定原文案】
|
||||
装修这几个时间点必须停工。
|
||||
砌墙结束之后,要停工 5 天。
|
||||
水电完工之后,要停工两天。
|
||||
防水刷完之后,要停工 3 天。
|
||||
瓷砖贴完之后,要停工 5 天。
|
||||
美缝做完之后,要停工两天。
|
||||
腻子刮完之后,要停工 3 天。
|
||||
乳胶漆刷完之后,要停工 7 天。
|
||||
关注我,装修不踩坑。
|
||||
【内置完整素材库标题】
|
||||
砌墙完工整体展示-新建砌筑
|
||||
水电完工全屋环视-水电验收
|
||||
防水涂层完工特写-防水施工
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
美缝施工-美缝开荒
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段人物出镜
|
||||
中间内容全部用空镜,空镜(内置完整素材库标题)与文案内容需匹配
|
||||
结尾的分镜为:一段人物出镜
|
||||
“分镜文案 “等于” 配音文案”,“配音文案”严格按照每句一段。
|
||||
每个分镜的 “分镜时长” 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 “分镜文案” 的纯文字字数 / 4},严格控制在 1-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需完全匹配
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配)
|
||||
voiceover: “配音文案”(严格与文案内容匹配)
|
||||
duration: “分镜时长”(如 “2s”,时长为 “配音文案” 的字数(含数字,不含标点符号)/4,严格控制在 1-8 秒,可以是两位小数,如 “不要正五孔插座” 总共 7个文字,则是 “1.75s”)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “装修这几个时间点必须停工。”,
|
||||
“duration”: “3.00s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “砌墙完工整体展示-新建砌筑”,
|
||||
“voiceover”: “砌墙结束之后,要停工5天。”,
|
||||
“duration”: “2.75s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “水电完工全屋环视-水电验收”,
|
||||
“voiceover”: “水电完工之后,要停工两天。”,
|
||||
“duration”: “2.75s”
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,121 +1,121 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备做全屋定制、担心被套路加价、不懂板材区分、被花式名称忽悠、合同暗藏增项的装修业主,严格从给到8个全屋定制大坑中每次随机选3个重新编排顺序创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机3个全屋定制避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:保留原文完整开头结构与核心原意,仅微调口语语气,不篡改句意,直击全屋定制合同签完仍乱加价、套路多的痛点,引出3个必看避坑要点。
|
||||
中间核心:固定从8个全屋定制坑位里每次随机抽取3个、自动打乱重新排序;文案可适当微调句式、口语化适配口播,完整保留每个坑原意、专业参数、选购逻辑不变;严格控制纯文字+数字字数360-480字,对应时长90-120s。
|
||||
结尾范式:完整保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动领福利、评论区扣关键词的核心逻辑。
|
||||
【开篇&语言要求】
|
||||
开篇钩子直击全屋定制水深、套路多、签合同还加价、不懂板材容易被坑的痛点,3秒抓眼球不拖沓,完全沿用原文开头核心话术不变。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站业主共情立场,贴合原文接地气口播风格。
|
||||
可微调句式语序,严禁篡改板材名称、环保等级、投影价格、铰链品牌、合同标注要求等核心细节,每句带标点规范断句。
|
||||
【内置固定原文案】
|
||||
全屋定制就是装修最大的坑,就算签了合同,照样加钱加到你想骂人,看我教你怎么应对。建议先点赞收藏,多看几遍,至少能帮你省好几万。
|
||||
第一,有人跟你说柜子用的是塑板,让他有多远滚多远,说白了就是假货。在厂里自己贴的面皮板材,什么品牌用的什么胶,他会跟你说实话吗?
|
||||
第二,我看谁还在现场找木工,现场打柜子,木工给你打个柜子,你还得屁颠儿屁颠儿跑到建材市场去买板材。而且现在好手艺的木工不好找,打出来的柜子工艺不行,钱也花了白费,省那点钱还不够你跑建材市场耗的油费。
|
||||
第三,什么禾香板、芦花板、竹香板、爱心板、康醇板、康净板,反正这些乱七八糟的,我给你一句话总结,全是颗粒板,就是取了好听的名字。就像你们去理发,一个叫理发师,一个叫托尼。他们回家还是叫张三李四,本质都是一类人,你甭管他叫啥,只要环保等级达到E0 级、或者是ENF 级的,你就可以直接闭着眼睛用。你要清楚的是,那些爱起花里胡哨名字的,无非就是那些所谓的大品牌。
|
||||
第四,不管什么品牌的全屋定制,无非就那几种,颗粒板、多层板、细木工板、欧松板、生态板。生态板里面就是木头块,多层板里面就是木头片,颗粒板里面就是木头渣子,欧松板里面就是大木片。你搞不懂就不用深究,你记住,北方的柜门柜体都是用颗粒板和香板,南方的柜体都是用多层板,柜门就用欧松板,因为柜体层板不变形,防水稳定性好,结构稳定性强。欧松板最大的优势就是稳定性强,不容易变形,所以柜门就用欧松板。不管南方还是北方,厨房阳台的柜体都用多层板。柜门参考我说的南方和北方的去选择,其他板材都不用考虑价格,北方一个投影面积不过 650,南方不超过 750 块钱,超过了就赶紧走。
|
||||
第五,不管是衣柜还是橱柜,柜门别选高光的,看着廉价,用个大半年全是刮痕手印,很多人说橱柜用高光的好搞卫生,实际上手一摸全是手印。还有 PET 材质的说的像婴儿皮肤一样,我劝你不要用,真的不耐刮,万一刮坏了还没办法修复。我自己家里用的全是双饰面的,抗刮抗造。装修公司只为装修完工那一刻让你满意。咱过日子要的是实用,不要听装修公司和设计师的忽悠,你听不到实话,多问问装修过的业主,他们使用过程中哪种好用你就选哪一种。
|
||||
第六就是铰链,你问他什么品牌,但凡跟你说是他们自有品牌,直接让他有多远滚多远。他又不是生产队的驴,啥都能生产。多半是找小工厂代工的,别为了省那点钱,铰链就认准汉高、东泰、德蒂,每天都要开关,咱们可不能马虎。
|
||||
第七,也是最重要的一点,一定要在合同上写明用的是什么品牌的板材,环保等级是什么,厚度是多少,哪些是增项,而且要写上假一赔十,全部落到纸上,不要光靠口头承诺。
|
||||
第八,全屋定制,不管是橱柜也好,衣柜也好,一线品牌和六线品牌做出来都是一模一样的。说白了,所有全屋定制都是板材的二道贩子,咱们就找本地工厂,关键看设计和安装。
|
||||
要是还有不懂的、近期准备新房装修的朋友,我整理了一份装修避坑手册供你参考,评论区抠避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近全屋定制主题,优先选工地恶搞、装修合同核对、柜体木作等相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选柜体木作、板材裁切、装修合同核对等贴合全屋定制主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离360–480(含数字,不含标点符号)、总时长偏离90–120秒。
|
||||
禁止篡改原文全屋定制避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7个细节记牢”,
|
||||
“duration”: “5.50s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这7个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备做全屋定制、担心被套路加价、不懂板材区分、被花式名称忽悠、合同暗藏增项的装修业主,严格从给到8个全屋定制大坑中每次随机选3个重新编排顺序创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机3个全屋定制避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:保留原文完整开头结构与核心原意,仅微调口语语气,不篡改句意,直击全屋定制合同签完仍乱加价、套路多的痛点,引出3个必看避坑要点。
|
||||
中间核心:固定从8个全屋定制坑位里每次随机抽取3个、自动打乱重新排序;文案可适当微调句式、口语化适配口播,完整保留每个坑原意、专业参数、选购逻辑不变;严格控制纯文字+数字字数360-480字,对应时长90-120s。
|
||||
结尾范式:完整保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动领福利、评论区回复关键词的核心逻辑。
|
||||
【开篇&语言要求】
|
||||
开篇钩子直击全屋定制水深、套路多、签合同还加价、不懂板材容易被坑的痛点,3秒抓眼球不拖沓,完全沿用原文开头核心话术不变。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站业主共情立场,贴合原文接地气口播风格。
|
||||
可微调句式语序,严禁篡改板材名称、环保等级、投影价格、铰链品牌、合同标注要求等核心细节,每句带标点规范断句。
|
||||
【内置固定原文案】
|
||||
全屋定制就是装修最大的坑,就算签了合同,照样加钱加到你想骂人,看我教你怎么应对。建议先点赞收藏,多看几遍,至少能帮你省好几万。
|
||||
第一,有人跟你说柜子用的是塑板,让他有多远滚多远,说白了就是假货。在厂里自己贴的面皮板材,什么品牌用的什么胶,他会跟你说实话吗?
|
||||
第二,我看谁还在现场找木工,现场打柜子,木工给你打个柜子,你还得屁颠儿屁颠儿跑到建材市场去买板材。而且现在好手艺的木工不好找,打出来的柜子工艺不行,钱也花了白费,省那点钱还不够你跑建材市场耗的油费。
|
||||
第三,什么禾香板、芦花板、竹香板、爱心板、康醇板、康净板,反正这些乱七八糟的,我给你一句话总结,全是颗粒板,就是取了好听的名字。就像你们去理发,一个叫理发师,一个叫托尼。他们回家还是叫张三李四,本质都是一类人,你甭管他叫啥,只要环保等级达到E0 级、或者是ENF 级的,你就可以直接闭着眼睛用。你要清楚的是,那些爱起花里胡哨名字的,无非就是那些所谓的大品牌。
|
||||
第四,不管什么品牌的全屋定制,无非就那几种,颗粒板、多层板、细木工板、欧松板、生态板。生态板里面就是木头块,多层板里面就是木头片,颗粒板里面就是木头渣子,欧松板里面就是大木片。你搞不懂就不用深究,你记住,北方的柜门柜体都是用颗粒板和香板,南方的柜体都是用多层板,柜门就用欧松板,因为柜体层板不变形,防水稳定性好,结构稳定性强。欧松板最大的优势就是稳定性强,不容易变形,所以柜门就用欧松板。不管南方还是北方,厨房阳台的柜体都用多层板。柜门参考我说的南方和北方的去选择,其他板材都不用考虑价格,北方一个投影面积不过 650,南方不超过 750 块钱,超过了就赶紧走。
|
||||
第五,不管是衣柜还是橱柜,柜门别选高光的,看着廉价,用个大半年全是刮痕手印,很多人说橱柜用高光的好搞卫生,实际上手一摸全是手印。还有 PET 材质的说的像婴儿皮肤一样,我劝你不要用,真的不耐刮,万一刮坏了还没办法修复。我自己家里用的全是双饰面的,抗刮抗造。装修公司只为装修完工那一刻让你满意。咱过日子要的是实用,不要听装修公司和设计师的忽悠,你听不到实话,多问问装修过的业主,他们使用过程中哪种好用你就选哪一种。
|
||||
第六就是铰链,你问他什么品牌,但凡跟你说是他们自有品牌,直接让他有多远滚多远。他又不是生产队的驴,啥都能生产。多半是找小工厂代工的,别为了省那点钱,铰链就认准汉高、东泰、德蒂,每天都要开关,咱们可不能马虎。
|
||||
第七,也是最重要的一点,一定要在合同上写明用的是什么品牌的板材,环保等级是什么,厚度是多少,哪些是增项,而且要写上假一赔十,全部落到纸上,不要光靠口头承诺。
|
||||
第八,全屋定制,不管是橱柜也好,衣柜也好,一线品牌和六线品牌做出来都是一模一样的。说白了,所有全屋定制都是板材的二道贩子,咱们就找本地工厂,关键看设计和安装。
|
||||
要是还有不懂的、近期准备新房装修的朋友,我整理了一份装修避坑手册供你参考,评论区回复避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近全屋定制主题,优先选工地恶搞、装修合同核对、柜体木作等相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选柜体木作、板材裁切、装修合同核对等贴合全屋定制主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离360–480(含数字,不含标点符号)、总时长偏离90–120秒。
|
||||
禁止篡改原文全屋定制避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7个细节记牢”,
|
||||
“duration”: “5.50s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这7个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
]
|
||||
@@ -1,261 +1,101 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修不懂全程监工、盲目盯工地白费精力、不知道哪些节点必须到场把控的装修业主,围绕装修 6 大必在场监工关键时间点创作,每次生成随机打乱 6 个要点顺序重新编排,保留原意不变。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 6 个装修必到场监工干货 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,用接地气实话视角点出业主全程无效监工痛点,引出下文 6 个关键监工节点。
|
||||
中间核心(6 个装修必在场监工要点,文案适当调整修改,意思保持原意,每次生成自动随机打乱重新编排顺序):
|
||||
封阳台施工必须在场,监督师傅做好窗户外沿防水斜坡,避免后期雨水倒灌入户。
|
||||
乳胶漆涂刷节点要到场,严格把控一遍底漆两遍面漆,先小面积试色再大面积滚涂。
|
||||
卫生间回填务必亲自在场,坚持用陶粒规范回填,杜绝建筑垃圾糊弄划破防水层。
|
||||
吊顶施工关键节点要在场,确认使用轻钢龙骨,防止偷换木龙骨造成后期变形发霉。
|
||||
全屋定制安装必须到场,通过五金孔查验板材品质,监督做好封边避免甲醛超标。
|
||||
闭水试验做完后,一定要亲自下楼查验有无渗漏,别只信师傅拍照规避后期赔付风险。
|
||||
(备注:保留原文 6 个要点核心细节和避坑逻辑,适当调整句式让口语化更贴合口播;每次生成随机打乱 6 条顺序,不固定排序,完整保留每条施工要求与隐患提醒,不篡改原意)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:内置 6 个装修关键监工固定要点,每次生成脚本自动随机打乱重新排序,不按原文固定顺序,避免内容同质化,适配短视频日更需求。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面表述改成抖音接地气口播大白话,不改变每个节点的施工要求、到场必要性、后期隐患,所有细节完整保留。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 360-440 字,按每秒 4 个纯文字计算,对应时长 90-110s,内容精炼不啰嗦,节奏适中符合短视频完播习惯。
|
||||
内容适配性:打乱顺序后文案衔接自然,每个节点独立成段适配空镜分镜,直击业主不用全程死盯、只抓关键节点就行的核心痛点,每一点都讲清到场理由和避坑重点。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领资料、评论区扣关键词、福利引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头朴实话术,3 秒抓眼球,点破全程监工又累又没用的现实,引出只盯关键节点的核心观点。
|
||||
全程口语化大白话,小白易懂、接地气实在,站普通业主视角共情讲解,不生硬说教,语气真诚接地气。
|
||||
可微调句式语序,严禁篡改 6 个监工节点的施工细节、到场要求、隐患后果,每句带标点规范断句,适配口播节奏,避免大长句。
|
||||
【内置固定原文案】
|
||||
装修真的没必要全程监工,累不说,关键你是看不明白。再说了,师傅要是真想坑你,你站那儿也没用。今天我告诉你几个监工关键时间点,你必须在场。
|
||||
第一,封阳台你必须在场,让师傅把窗户外沿做好防水斜坡,不然后期雨水倒灌有你受的。
|
||||
第二,刷乳胶漆,你要在场,一遍底漆两遍面漆必须做到位,调好色的乳胶漆,先小面积试色,再大面积涂刷。
|
||||
第三,卫生间回填,你必须在场,一定记得用陶粒回填,千万别让工人用建筑垃圾糊弄。垃圾回填容易划破防水层,漏了水,你就等着砸砖吧。
|
||||
第四,吊顶时,你必须在场,确认好使用的是轻钢龙骨,别让师傅偷换用木龙骨,再直接封上石膏板,后期变形发霉,等你发现那就晚了。
|
||||
第五,全屋定制安装,你必须在场,通过五金孔检查板材品质,还要叮嘱师傅做好封边,少做一步,你家都可能甲醛超标。
|
||||
第六,房子做完闭水试验,你必须亲自去楼下邻居家看看有没有漏水,如果只让师傅拍照片,你根本不知道他是什么时候拍的。真出了问题还得你来赔付。
|
||||
记不住的,我整理了装修全流程避坑手册。评论区抠避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修监工、节点把控主题,优先选工地恶搞、墙面空鼓、毛坯全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选吊顶造型、防水施工、面漆涂刷、全屋定制相关空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修不懂全程监工、盲目盯工地白费精力、不知道哪些节点必须到场把控的装修业主,围绕装修 6 大必在场监工关键时间点创作,每次生成随机打乱 6 个要点顺序重新编排,保留原意不变。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 6 个装修必到场监工干货 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,用接地气实话视角点出业主全程无效监工痛点,引出下文 6 个关键监工节点。
|
||||
中间核心(6 个装修必在场监工要点,文案适当调整修改,意思保持原意,每次生成自动随机打乱重新编排顺序):
|
||||
封阳台施工必须在场,监督师傅做好窗户外沿防水斜坡,避免后期雨水倒灌入户。
|
||||
乳胶漆涂刷节点要到场,严格把控一遍底漆两遍面漆,先小面积试色再大面积滚涂。
|
||||
卫生间回填务必亲自在场,坚持用陶粒规范回填,杜绝建筑垃圾糊弄划破防水层。
|
||||
吊顶施工关键节点要在场,确认使用轻钢龙骨,防止偷换木龙骨造成后期变形发霉。
|
||||
全屋定制安装必须到场,通过五金孔查验板材品质,监督做好封边避免甲醛超标。
|
||||
闭水试验做完后,一定要亲自下楼查验有无渗漏,别只信师傅拍照规避后期赔付风险。
|
||||
(备注:保留原文 6 个要点核心细节和避坑逻辑,适当调整句式让口语化更贴合口播;每次生成随机打乱 6 条顺序,不固定排序,完整保留每条施工要求与隐患提醒,不篡改原意)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:内置 6 个装修关键监工固定要点,每次生成脚本自动随机打乱重新排序,不按原文固定顺序,避免内容同质化,适配短视频日更需求。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面表述改成抖音接地气口播大白话,不改变每个节点的施工要求、到场必要性、后期隐患,所有细节完整保留。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 360-440 字,按每秒 4 个纯文字计算,对应时长 90-110s,内容精炼不啰嗦,节奏适中符合短视频完播习惯。
|
||||
内容适配性:打乱顺序后文案衔接自然,每个节点独立成段适配空镜分镜,直击业主不用全程死盯、只抓关键节点就行的核心痛点,每一点都讲清到场理由和避坑重点。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领资料、评论区回复关键词、福利引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头朴实话术,3 秒抓眼球,点破全程监工又累又没用的现实,引出只盯关键节点的核心观点。
|
||||
全程口语化大白话,小白易懂、接地气实在,站普通业主视角共情讲解,不生硬说教,语气真诚接地气。
|
||||
可微调句式语序,严禁篡改 6 个监工节点的施工细节、到场要求、隐患后果,每句带标点规范断句,适配口播节奏,避免大长句。
|
||||
【内置固定原文案】
|
||||
装修真的没必要全程监工,累不说,关键你是看不明白。再说了,师傅要是真想坑你,你站那儿也没用。今天我告诉你几个监工关键时间点,你必须在场。
|
||||
第一,封阳台你必须在场,让师傅把窗户外沿做好防水斜坡,不然后期雨水倒灌有你受的。
|
||||
第二,刷乳胶漆,你要在场,一遍底漆两遍面漆必须做到位,调好色的乳胶漆,先小面积试色,再大面积涂刷。
|
||||
第三,卫生间回填,你必须在场,一定记得用陶粒回填,千万别让工人用建筑垃圾糊弄。垃圾回填容易划破防水层,漏了水,你就等着砸砖吧。
|
||||
第四,吊顶时,你必须在场,确认好使用的是轻钢龙骨,别让师傅偷换用木龙骨,再直接封上石膏板,后期变形发霉,等你发现那就晚了。
|
||||
第五,全屋定制安装,你必须在场,通过五金孔检查板材品质,还要叮嘱师傅做好封边,少做一步,你家都可能甲醛超标。
|
||||
第六,房子做完闭水试验,你必须亲自去楼下邻居家看看有没有漏水,如果只让师傅拍照片,你根本不知道他是什么时候拍的。真出了问题还得你来赔付。
|
||||
记不住的,我整理了装修全流程避坑手册。评论区回复避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
讨好装修师傅
|
||||
封窗施工
|
||||
阳台窗外防水斜坡
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
卫生间陶粒回填
|
||||
防水翻车漏水-施工翻车
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
全屋定制板材检查
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:(可选用讨好装修师傅、恶搞开篇或施工翻车镜,最好能贴近话术内容和主题)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "讨好装修师傅",
|
||||
"voiceover": "装修真的没必要全程监工,累不说,关键你是看不明白!",
|
||||
"duration": "5.50s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "再说了,师傅要是真想坑你,你站那儿也没用。",
|
||||
"duration": "4.50s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "墙体掉落-施工翻车",
|
||||
"voiceover": "今天我告诉你几个监工关键时间点,你必须在场。",
|
||||
"duration": "5.00s"
|
||||
}
|
||||
]
|
||||
@@ -1,270 +1,270 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、不懂水电改造套路、容易被网红颜值工艺忽悠、只看表面好看多花冤枉钱,后期入住返工留遗憾的业主,严格从10 个水电改造大坑中随机抽取 4 个进行避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修水电避坑口播短视频脚本,结构固定:范式化定制开头 + 随机 4 个水电避坑干货 + 保留原文结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
以 **“新房装修做水电改造,谁要是只追求网红大弧弯、横平竖直的表面颜值,只顾好看不考虑实用,千万别盲目跟风照搬。看着工艺漂亮上档次,其实全是装修公司收割你的面子工程,多花钱还不实用。下面这 4 个水电改造大坑一定要提前避开,看懂少花几万冤枉钱!”** 为固定核心句式,沿用原文 “水电好看都是面子工程、宰客套路” 的核心原意,用警示性语气点出颜值陷阱、多花冤枉钱的痛点,引出下文 4 个坑点,不照搬原文完整长开头,只保留核心立意适配范式结构。
|
||||
中间核心
|
||||
固定从给到的 10 个水电改造坑中随机选 4 个,重新自主打乱编排顺序;文案可适当微调句式、口语化润色,保留每个坑原意、数字标准、材料型号、施工禁忌、避坑逻辑完全不变,不篡改任何核心细节;严格控制纯文字 + 数字字数400-480 字,对应时长100-120s。
|
||||
(备注:每次生成均随机抽取 4 个、打乱重新排序,不固定组合、不固定顺序;只优化口语语感,不改数据、不改工艺、不改避坑要点,严格卡字数和时长区间)
|
||||
10 个水电原始坑点汇总
|
||||
1、100 平改水电超 7000 就是被宰,国产 PPR 水管够用不用买进口,电线选 BV 线耐用稳定
|
||||
2、埋管穿线必须做整根活线,严禁电线中间留接头,避免后期电路故障无法检修
|
||||
3、不用全屋通铺 25 水管,入户用 25、室内分支用 20,粗细搭配水压才正常
|
||||
4、水电开槽尽量不开横槽,横槽超过 50 公分后期墙面必开裂,修补难度大
|
||||
5、弱电包锡纸、水路大弯都是增项面子工程,六类以上网线自带屏蔽,大弯直角水压无区别
|
||||
6、非 20 年老房子不用水电全改,做点对点局部改造,缺哪补哪更省钱实用
|
||||
7、厨房下水存水弯改成 90°,避免橱柜遮挡检修口,长期使用容易堵塞无法疏通
|
||||
8、冰箱、摄像头、燃气报警器等不断电设备,必须单独走独立回路,离家断电也安全
|
||||
9、开关插座别在实体店、楼下五金店和工人手上买,溢价高假货多,网上买更划算保真
|
||||
10、水电不用盲目走顶,品牌水管有打压质保、维修概率极低,被忽悠走顶纯属被割韭菜
|
||||
结尾范式
|
||||
完整保留原文结尾原话一字不变,仅可轻微口语化顺滑微调,不改动装修准备、整理避坑手册、回复关键词领取参考的引流引导逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇采用固定范式句式,紧扣原文 “水电颜值工艺是面子工程、装修宰客” 核心,3 秒直击业主跟风踩坑、多花冤枉钱痛点,不照搬原文长文案,只保留核心立意。
|
||||
全程沿用原文接地气吐槽大白话,内行视角讲干货,直白易懂不生硬说教,贴合装修业主共情口吻。
|
||||
仅可微调语序、精简冗余语句,严禁改动 10 个坑里面的价格、尺寸、管材型号、施工标准、隐患后果,每句必须带标点规范断句,适配口播节奏。
|
||||
【内置固定原文案】
|
||||
改水电就是你装修被宰的第一刀,干得越漂亮,这一刀就扎得越深。什么好看的大弧弯,横平竖直,看起来是好看,但其实大多数都是面子工程,除了让你多花钱,实际用处一点都没有。水电改造真正重要的 10 个细节你要记住了,就不可能踩坑,全是干货。建议你点赞收藏慢慢看。
|
||||
首先,100 平的房子改水电,如果超过 7000 块,你就是被宰了。记住,水管只要是 PPR 管,无论是保利、伟星、日丰哪个国产牌子,都可以,让你买进口的都是看你好骗。电线你就选 BV 线,导电性能稳定,耐用几十年。
|
||||
第二,埋管穿线的时候一定要确保每根电线都是活线,那些不给你用整根电线穿线、还出现接头的,你让他有多远滚多远,后期电路出问题,你都找不到原因。
|
||||
第三,现在的装修公司都建议你水管用 25 的,说水压大,入住以后你发现水压没有明显的变化。真正的做法是,入户门到室内用 25 的,其他的水管用 20 的就行了。水管从粗到细,水压才能变大,你都换成 25 的根本没有必要。
|
||||
第四,水电管都是开槽安装的,横平竖直是真的好看,但是装修公司不会告诉你,横管长度超过 50 公分后,刷完漆必然开裂,修都不好修,一定要告诉师傅,没必要尽量不要开横槽。
|
||||
第五,弱电锡纸的包裹、水路大弯工艺等,这些都是容易增项的。现在超过六类的网线基本上都是自带屏蔽功能,包锡纸也是个样子工程,根本没必要。还有大弯水管和直角水管,真的没有水压大小的区别。
|
||||
第六,如果你不是 20 年前的老房子,水电没必要全改,去做点对点改造,哪里不够就加哪里,这样省钱还不影响使用。
|
||||
第七,厨房的下水存水弯必须改成 90°,不然贴完瓷砖、装好橱柜,原始检修口几乎和橱柜底板挨着,根本打不开。时间一长,垃圾冲也冲不动、扣也扣不着,很容易堵塞。
|
||||
第八,家里的冰箱、摄像头、燃气报警器这些不能断电的设备,一定要嘱咐师傅单独走回路,以后出啥远门都不影响,杜绝安全隐患。
|
||||
第九,开关插座完全没有必要去实体店买,尤其楼下那些小五金店,很多都是假货,成本可能只有五六块钱一个,却卖到三四十块钱一个,你说这有良心吗?网上购买不仅价格实惠,而且更容易买到正品。如果装修工人给你带的开关插座,我劝你不要用,因为这些成本可能只有两三块钱一个。
|
||||
第十,水电走地好,如果师傅跟你说水电走顶好维修、还不会抬高地面,那他就是逮着你割韭菜了。现在品牌的水管完工后都会上门打压测试,维修概率极低。而且,你要是有了质保,后期真出问题,赔的都够你再买一套房子。
|
||||
如果你也准备新房装修,我整理了一份装修避坑手册,回个手册发你参考。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴近水电改造、施工翻车、装修套路主题,优先选工地恶搞、墙面空鼓、毛坯全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分点阐述全部用空镜,空镜素材库标题与文案内容需精准匹配,匹配不到则优先选水电验收、水路施工、电路施工、墙面开槽等水电相关近似空镜。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分镜文案 = 配音文案,必须要有标点符号断句,避免大长句;每段分镜文案纯文字含数字、不含标点严格控制 12-32 个字,超长句必须拆分多分镜,语句通顺完整。
|
||||
全篇文案硬性约束:纯文字 + 数字扣除标点严控400-480 字、总时长锁定100-120s,不得偏离区间。
|
||||
每个分镜时长计算:严格按每秒 4 个纯文字核算,纯文字只统计汉字 + 阿拉伯数字、剔除标点;时长保留两位小数,单镜时长强制锁定 3-8 秒,超标必须拆句重分镜。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方内置素材库选匹配标题。
|
||||
人物出镜画面允许语句语意顺延到下一分镜;空镜必须贴合当前配音文案水电避坑主题。
|
||||
每次创作自动从 10 个水电坑随机选 4 个、重新打乱排序,不固定组合、不固定顺序。
|
||||
禁止篡改原文 10 个水电坑的价格、尺寸、材料、施工工艺、避坑核心逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合装修业主水电避坑痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "贴砖恶搞 - 恶搞开篇",
|
||||
"voiceover": "瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "瓷砖铺贴 - 瓷砖铺贴",
|
||||
"voiceover": "先说好瓷砖排版,别让瓦工做,商家免费排更精准",
|
||||
"duration": "5.00s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、不懂水电改造套路、容易被网红颜值工艺忽悠、只看表面好看多花冤枉钱,后期入住返工留遗憾的业主,严格从10 个水电改造大坑中随机抽取 4 个进行避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修水电避坑口播短视频脚本,结构固定:范式化定制开头 + 随机 4 个水电避坑干货 + 保留原文结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
以 **“新房装修做水电改造,谁要是只追求网红大弧弯、横平竖直的表面颜值,只顾好看不考虑实用,千万别盲目跟风照搬。看着工艺漂亮上档次,其实全是装修公司收割你的面子工程,多花钱还不实用。下面这 4 个水电改造大坑一定要提前避开,看懂少花几万冤枉钱!”** 为固定核心句式,沿用原文 “水电好看都是面子工程、宰客套路” 的核心原意,用警示性语气点出颜值陷阱、多花冤枉钱的痛点,引出下文 4 个坑点,不照搬原文完整长开头,只保留核心立意适配范式结构。
|
||||
中间核心
|
||||
固定从给到的 10 个水电改造坑中随机选 4 个,重新自主打乱编排顺序;文案可适当微调句式、口语化润色,保留每个坑原意、数字标准、材料型号、施工禁忌、避坑逻辑完全不变,不篡改任何核心细节;严格控制纯文字 + 数字字数400-480 字,对应时长100-120s。
|
||||
(备注:每次生成均随机抽取 4 个、打乱重新排序,不固定组合、不固定顺序;只优化口语语感,不改数据、不改工艺、不改避坑要点,严格卡字数和时长区间)
|
||||
10 个水电原始坑点汇总
|
||||
1、100 平改水电超 7000 就是被宰,国产 PPR 水管够用不用买进口,电线选 BV 线耐用稳定
|
||||
2、埋管穿线必须做整根活线,严禁电线中间留接头,避免后期电路故障无法检修
|
||||
3、不用全屋通铺 25 水管,入户用 25、室内分支用 20,粗细搭配水压才正常
|
||||
4、水电开槽尽量不开横槽,横槽超过 50 公分后期墙面必开裂,修补难度大
|
||||
5、弱电包锡纸、水路大弯都是增项面子工程,六类以上网线自带屏蔽,大弯直角水压无区别
|
||||
6、非 20 年老房子不用水电全改,做点对点局部改造,缺哪补哪更省钱实用
|
||||
7、厨房下水存水弯改成 90°,避免橱柜遮挡检修口,长期使用容易堵塞无法疏通
|
||||
8、冰箱、摄像头、燃气报警器等不断电设备,必须单独走独立回路,离家断电也安全
|
||||
9、开关插座别在实体店、楼下五金店和工人手上买,溢价高假货多,网上买更划算保真
|
||||
10、水电不用盲目走顶,品牌水管有打压质保、维修概率极低,被忽悠走顶纯属被割韭菜
|
||||
结尾范式
|
||||
完整保留原文结尾原话一字不变,仅可轻微口语化顺滑微调,不改动装修准备、整理避坑手册、回复关键词领取参考的引流引导逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇采用固定范式句式,紧扣原文 “水电颜值工艺是面子工程、装修宰客” 核心,3 秒直击业主跟风踩坑、多花冤枉钱痛点,不照搬原文长文案,只保留核心立意。
|
||||
全程沿用原文接地气吐槽大白话,内行视角讲干货,直白易懂不生硬说教,贴合装修业主共情口吻。
|
||||
仅可微调语序、精简冗余语句,严禁改动 10 个坑里面的价格、尺寸、管材型号、施工标准、隐患后果,每句必须带标点规范断句,适配口播节奏。
|
||||
【内置固定原文案】
|
||||
改水电就是你装修被宰的第一刀,干得越漂亮,这一刀就扎得越深。什么好看的大弧弯,横平竖直,看起来是好看,但其实大多数都是面子工程,除了让你多花钱,实际用处一点都没有。水电改造真正重要的 10 个细节你要记住了,就不可能踩坑,全是干货。建议你点赞收藏慢慢看。
|
||||
首先,100 平的房子改水电,如果超过 7000 块,你就是被宰了。记住,水管只要是 PPR 管,无论是保利、伟星、日丰哪个国产牌子,都可以,让你买进口的都是看你好骗。电线你就选 BV 线,导电性能稳定,耐用几十年。
|
||||
第二,埋管穿线的时候一定要确保每根电线都是活线,那些不给你用整根电线穿线、还出现接头的,你让他有多远滚多远,后期电路出问题,你都找不到原因。
|
||||
第三,现在的装修公司都建议你水管用 25 的,说水压大,入住以后你发现水压没有明显的变化。真正的做法是,入户门到室内用 25 的,其他的水管用 20 的就行了。水管从粗到细,水压才能变大,你都换成 25 的根本没有必要。
|
||||
第四,水电管都是开槽安装的,横平竖直是真的好看,但是装修公司不会告诉你,横管长度超过 50 公分后,刷完漆必然开裂,修都不好修,一定要告诉师傅,没必要尽量不要开横槽。
|
||||
第五,弱电锡纸的包裹、水路大弯工艺等,这些都是容易增项的。现在超过六类的网线基本上都是自带屏蔽功能,包锡纸也是个样子工程,根本没必要。还有大弯水管和直角水管,真的没有水压大小的区别。
|
||||
第六,如果你不是 20 年前的老房子,水电没必要全改,去做点对点改造,哪里不够就加哪里,这样省钱还不影响使用。
|
||||
第七,厨房的下水存水弯必须改成 90°,不然贴完瓷砖、装好橱柜,原始检修口几乎和橱柜底板挨着,根本打不开。时间一长,垃圾冲也冲不动、扣也扣不着,很容易堵塞。
|
||||
第八,家里的冰箱、摄像头、燃气报警器这些不能断电的设备,一定要嘱咐师傅单独走回路,以后出啥远门都不影响,杜绝安全隐患。
|
||||
第九,开关插座完全没有必要去实体店买,尤其楼下那些小五金店,很多都是假货,成本可能只有五六块钱一个,却卖到三四十块钱一个,你说这有良心吗?网上购买不仅价格实惠,而且更容易买到正品。如果装修工人给你带的开关插座,我劝你不要用,因为这些成本可能只有两三块钱一个。
|
||||
第十,水电走地好,如果师傅跟你说水电走顶好维修、还不会抬高地面,那他就是逮着你割韭菜了。现在品牌的水管完工后都会上门打压测试,维修概率极低。而且,你要是有了质保,后期真出问题,赔的都够你再买一套房子。
|
||||
如果你也准备新房装修,我整理了一份装修避坑手册,回个手册发你参考。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴近水电改造、施工翻车、装修套路主题,优先选工地恶搞、墙面空鼓、毛坯全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分点阐述全部用空镜,空镜素材库标题与文案内容需精准匹配,匹配不到则优先选水电验收、水路施工、电路施工、墙面开槽等水电相关近似空镜。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分镜文案 = 配音文案,必须要有标点符号断句,避免大长句;每段分镜文案纯文字含数字、不含标点严格控制 12-32 个字,超长句必须拆分多分镜,语句通顺完整。
|
||||
全篇文案硬性约束:纯文字 + 数字扣除标点严控400-480 字、总时长锁定100-120s,不得偏离区间。
|
||||
每个分镜时长计算:严格按每秒 4 个纯文字核算,纯文字只统计汉字 + 阿拉伯数字、剔除标点;时长保留两位小数,单镜时长强制锁定 3-8 秒,超标必须拆句重分镜。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方内置素材库选匹配标题。
|
||||
人物出镜画面允许语句语意顺延到下一分镜;空镜必须贴合当前配音文案水电避坑主题。
|
||||
每次创作自动从 10 个水电坑随机选 4 个、重新打乱排序,不固定组合、不固定顺序。
|
||||
禁止篡改原文 10 个水电坑的价格、尺寸、材料、施工工艺、避坑核心逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合装修业主水电避坑痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "贴砖恶搞 - 恶搞开篇",
|
||||
"voiceover": "瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "瓷砖铺贴 - 瓷砖铺贴",
|
||||
"voiceover": "先说好瓷砖排版,别让瓦工做,商家免费排更精准",
|
||||
"duration": "5.00s"
|
||||
}
|
||||
]
|
||||
@@ -1,255 +1,255 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:正在做家装水电改造、不懂施工关键要点,担心装错后期返工花钱多、留下隐蔽隐患的装修业主,严格围绕水电施工关键避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 4 个水电施工关键干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:水电改造】,谁要是忽略水电施工关键要点,随便任由师傅施工,你就直接【拒绝动作:别敷衍大意】。你以为只是普通隐蔽工程,其实一旦做错返工就要花大价钱。下面这 4 个关键点一定要记牢,错一个都后悔莫及!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(4 个水电施工关键要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
水管更换:开发商原配 PVC 水管全部换掉,选用日丰 PPR 管材,质保时间长,居家用水更安心靠谱。
|
||||
电路布线:电路无需全拆全改,厨卫空调专线用 4 平方国标铜线,普通区域选用 2.5 平方国标铜线即可。
|
||||
走管方式:厨卫水电统一走顶,漏水易发现、后期维修方便;其余空间走地施工,节省装修材料成本。
|
||||
完工验收:水电完工必须做 30 分钟水管打压,确保无渗漏,电路检测通断正常后,再签字确认验收。
|
||||
(备注:保留原文 4 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当微调句式贴合口播,严格控制纯文字 + 数字 170-210 字,适配时长 42.5-52.5s)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修避坑手册】,抠【核心关键词:避坑】直接拿走,对照参考少走弯路!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击水电装错隐患大、返工成本高的痛点,3 秒抓眼球,不拖沓不铺垫(保留原文 “水电装错毁一生,这几条关键点错一个返工要好几万” 核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文水电管材、电线平方、打压 30 分钟等核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
水电装错毁一生,这几条关键点错一个返工要好几万!
|
||||
1. 开发商留的PVC水管必须换,选日丰PPR管,质保够长才放心。
|
||||
2. 电路不用全拆全改,厨卫空调用4平方线,其余用2.5平方线,选国标铜线。
|
||||
3. 厨卫水电必走顶,漏水易发现好维修,其他地方走地省材料。
|
||||
4. 验收必做水管打压30分钟无渗漏,电路测通断再签字。
|
||||
水电是隐蔽工程,紧盯施工别偷懒,别等返工才追悔莫及!
|
||||
近期准备装修的可以找我领装修避坑手册,评论区扣避坑,直接拿走。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近水电主题,优先选水管错位、工地恶搞、水电完工环视等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选水路施工、电路施工、水电验收等贴合水电主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数。
|
||||
type 为 segment = 人物出镜;type=empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 170–210(含数字,不含标点符号)、总时长偏离 42.5–52.5 秒。
|
||||
禁止篡改原文水电施工避坑相关的管材、线径、打压时长等核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:正在做家装水电改造、不懂施工关键要点,担心装错后期返工花钱多、留下隐蔽隐患的装修业主,严格围绕水电施工关键避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 4 个水电施工关键干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:水电改造】,谁要是忽略水电施工关键要点,随便任由师傅施工,你就直接【拒绝动作:别敷衍大意】。你以为只是普通隐蔽工程,其实一旦做错返工就要花大价钱。下面这 4 个关键点一定要记牢,错一个都后悔莫及!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(4 个水电施工关键要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
水管更换:开发商原配 PVC 水管全部换掉,选用日丰 PPR 管材,质保时间长,居家用水更安心靠谱。
|
||||
电路布线:电路无需全拆全改,厨卫空调专线用 4 平方国标铜线,普通区域选用 2.5 平方国标铜线即可。
|
||||
走管方式:厨卫水电统一走顶,漏水易发现、后期维修方便;其余空间走地施工,节省装修材料成本。
|
||||
完工验收:水电完工必须做 30 分钟水管打压,确保无渗漏,电路检测通断正常后,再签字确认验收。
|
||||
(备注:保留原文 4 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当微调句式贴合口播,严格控制纯文字 + 数字 170-210 字,适配时长 42.5-52.5s)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修避坑手册】,回复【核心关键词:避坑】直接拿走,对照参考少走弯路!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击水电装错隐患大、返工成本高的痛点,3 秒抓眼球,不拖沓不铺垫(保留原文 “水电装错毁一生,这几条关键点错一个返工要好几万” 核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文水电管材、电线平方、打压 30 分钟等核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
水电装错毁一生,这几条关键点错一个返工要好几万!
|
||||
1. 开发商留的PVC水管必须换,选日丰PPR管,质保够长才放心。
|
||||
2. 电路不用全拆全改,厨卫空调用4平方线,其余用2.5平方线,选国标铜线。
|
||||
3. 厨卫水电必走顶,漏水易发现好维修,其他地方走地省材料。
|
||||
4. 验收必做水管打压30分钟无渗漏,电路测通断再签字。
|
||||
水电是隐蔽工程,紧盯施工别偷懒,别等返工才追悔莫及!
|
||||
近期准备装修的可以找我领装修避坑手册,评论区回复避坑,直接拿走。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近水电主题,优先选水管错位、工地恶搞、水电完工环视等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选水路施工、电路施工、水电验收等贴合水电主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数。
|
||||
type 为 segment = 人物出镜;type=empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 170–210(含数字,不含标点符号)、总时长偏离 42.5–52.5 秒。
|
||||
禁止篡改原文水电施工避坑相关的管材、线径、打压时长等核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
]
|
||||
@@ -1,258 +1,258 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将油工进场施工、不懂和油工师傅沟通话术,担心施工偷工减料、甲醛超标、墙面后期开裂掉皮的业主,严格围绕油工进场施工沟通避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 6 个油工施工沟通避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:油工进场】,很多业主不懂行任由师傅自由施工,你以为他是帮你【表面好处:省事、按常规做法施工】,其实他就是图【错误目的:偷工减料、敷衍了事】。下面这 6 句话一定要记牢,照着跟师傅说不踩坑!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6 个油工进场沟通要点,文案适当精简微调,意思保持原意,按原文序号排列,不随机抽取):
|
||||
墙固涂刷:跟师傅交代原始墙面涂刷高渗透墙固,工费自理,有效预防墙面开裂反碱。
|
||||
挂网范围:不用全屋整体挂网,只在新老墙体交接、石膏板接缝位置局部挂网即可。
|
||||
腻子配比:腻子里面只能加水,禁止添加其他胶水,规避甲醛超标,守护家人健康。
|
||||
墙面找平:门口、踢脚线、衣柜周边重点做墙面找平,避免后期留出难看缝隙。
|
||||
吊顶防锈:吊顶所有钉子眼,必须人工涂刷防锈漆,防止后期生锈泛黄影响颜值。
|
||||
验收付款:油工全部施工完毕,验收合格之后再结尾款,严把施工质量关。
|
||||
(备注:保留原文 6 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,精简句式,控制整体纯文字 + 数字字数在 180-220 字,贴合短时长口播语感)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修流程避坑手册】,抠【核心关键词:避坑】直接拿走!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击油工施工不懂沟通、容易被糊弄、墙面留隐患、甲醛超标的痛点,3 秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调精简句式,不得篡改原文油工施工沟通的核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
油工进场不想踩坑,这 6 句话一定要跟师傅说,听完就懂行!
|
||||
第一、跟师傅说原始墙刷高渗透墙固,工费我出,防开裂反碱。
|
||||
第二、不要全屋挂网,只在新老墙体、石膏板接缝处挂网就够。
|
||||
第三、腻子里除了水啥也不加,家里有老人小孩怕甲醛超标。
|
||||
第四、门口、踢脚线、衣柜周围重点找平,别留难看缝隙。
|
||||
第五、吊顶钉子眼一定要人工刷防锈漆,防止后期生锈难看。
|
||||
第六、油工验收合格再给钱,面子工程必须把好质量关。
|
||||
准备装修的朋友,评论区扣避坑直接领取装修流程避坑手册!直接拿着对照参考,少踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近油工主题,优先选墙面开裂、墙面空鼓、搞笑涂料施工等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙面基层、面漆涂刷、吊顶造型等贴合油工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数。
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment” 对应 “人物出镜”,人物出镜画面内容可语句顺延到下一画面。
|
||||
“empty_shot” 对应上述素材库标题,文案内容需匹配,匹配不上选近似空镜。
|
||||
禁止总字数偏离 180–220(含数字,不含标点符号)、总时长偏离 45–55 秒。
|
||||
禁止篡改原文油工施工沟通避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment” 或 “empty_shot”
|
||||
scene: “人物出镜” 或上述素材库标题
|
||||
voiceover: “配音文案”
|
||||
duration: “分镜时长”
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "搞笑涂料施工 - 恶搞开篇",
|
||||
"voiceover": "油工进场不想踩坑,记住这 6 句话就够了",
|
||||
"duration": "4.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "照着这 6 点跟油工师傅沟通,再也不怕被糊弄",
|
||||
"duration": "4.75s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "墙面基层 - 墙面基层",
|
||||
"voiceover": "第一,原始墙面刷高渗透墙固,自费也能防开裂反碱。",
|
||||
"duration": "5.25s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将油工进场施工、不懂和油工师傅沟通话术,担心施工偷工减料、甲醛超标、墙面后期开裂掉皮的业主,严格围绕油工进场施工沟通避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 6 个油工施工沟通避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:油工进场】,很多业主不懂行任由师傅自由施工,你以为他是帮你【表面好处:省事、按常规做法施工】,其实他就是图【错误目的:偷工减料、敷衍了事】。下面这 6 句话一定要记牢,照着跟师傅说不踩坑!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6 个油工进场沟通要点,文案适当精简微调,意思保持原意,按原文序号排列,不随机抽取):
|
||||
墙固涂刷:跟师傅交代原始墙面涂刷高渗透墙固,工费自理,有效预防墙面开裂反碱。
|
||||
挂网范围:不用全屋整体挂网,只在新老墙体交接、石膏板接缝位置局部挂网即可。
|
||||
腻子配比:腻子里面只能加水,禁止添加其他胶水,规避甲醛超标,守护家人健康。
|
||||
墙面找平:门口、踢脚线、衣柜周边重点做墙面找平,避免后期留出难看缝隙。
|
||||
吊顶防锈:吊顶所有钉子眼,必须人工涂刷防锈漆,防止后期生锈泛黄影响颜值。
|
||||
验收付款:油工全部施工完毕,验收合格之后再结尾款,严把施工质量关。
|
||||
(备注:保留原文 6 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,精简句式,控制整体纯文字 + 数字字数在 180-220 字,贴合短时长口播语感)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修流程避坑手册】,回复【核心关键词:避坑】直接拿走!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击油工施工不懂沟通、容易被糊弄、墙面留隐患、甲醛超标的痛点,3 秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调精简句式,不得篡改原文油工施工沟通的核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
油工进场不想踩坑,这 6 句话一定要跟师傅说,听完就懂行!
|
||||
第一、跟师傅说原始墙刷高渗透墙固,工费我出,防开裂反碱。
|
||||
第二、不要全屋挂网,只在新老墙体、石膏板接缝处挂网就够。
|
||||
第三、腻子里除了水啥也不加,家里有老人小孩怕甲醛超标。
|
||||
第四、门口、踢脚线、衣柜周围重点找平,别留难看缝隙。
|
||||
第五、吊顶钉子眼一定要人工刷防锈漆,防止后期生锈难看。
|
||||
第六、油工验收合格再给钱,面子工程必须把好质量关。
|
||||
准备装修的朋友,评论区回复避坑直接领取装修流程避坑手册!直接拿着对照参考,少踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近油工主题,优先选墙面开裂、墙面空鼓、搞笑涂料施工等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙面基层、面漆涂刷、吊顶造型等贴合油工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数。
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment” 对应 “人物出镜”,人物出镜画面内容可语句顺延到下一画面。
|
||||
“empty_shot” 对应上述素材库标题,文案内容需匹配,匹配不上选近似空镜。
|
||||
禁止总字数偏离 180–220(含数字,不含标点符号)、总时长偏离 45–55 秒。
|
||||
禁止篡改原文油工施工沟通避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment” 或 “empty_shot”
|
||||
scene: “人物出镜” 或上述素材库标题
|
||||
voiceover: “配音文案”
|
||||
duration: “分镜时长”
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "搞笑涂料施工 - 恶搞开篇",
|
||||
"voiceover": "油工进场不想踩坑,记住这 6 句话就够了",
|
||||
"duration": "4.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "照着这 6 点跟油工师傅沟通,再也不怕被糊弄",
|
||||
"duration": "4.75s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "墙面基层 - 墙面基层",
|
||||
"voiceover": "第一,原始墙面刷高渗透墙固,自费也能防开裂反碱。",
|
||||
"duration": "5.25s"
|
||||
}
|
||||
]
|
||||
@@ -1,269 +1,269 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修瓦工进场、不懂专业监工、只会送礼讨好师傅、想靠专业话术把控施工细节的装修业主,围绕瓦工施工 10 句必备监工话术创作,每次生成随机打乱 10 条话术顺序重新编排,保留原意不变。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 随机打乱 10 条瓦工监工话术 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,用接地气吐槽语气点出业主无效监工痛点,引出下文 10 句监工话术。
|
||||
中间核心(瓦工施工 10 句监工重点话术,文案可适当微调句式、口语化优化,保留每条原意不变,每次生成自动随机打乱重新编排顺序):
|
||||
入户瓷砖优先铺整块,全屋通铺,边角料藏在家具遮挡位置。
|
||||
有色差、破损瑕疵瓷砖不要铺贴,单独放置留作商家退换。
|
||||
卫生间地面做好排水坡度,地漏做最低点,管道铺贴无断层。
|
||||
卫生间下水管道先贴阻尼片、包隔音棉,再砌砖贴砖做好隔音。
|
||||
后期装铝合金踢脚线,提前把控墙面与瓷砖预留缝隙大小。
|
||||
卫生间做单包套,四周必须完整贴砖,避免后期额外增项花钱。
|
||||
墙面出水口做好密封处理,从源头杜绝后期墙面渗水隐患。
|
||||
瓷砖转角统一做海棠角,预留美缝空间,禁止加装阳角条。
|
||||
止逆阀位置铺贴整块瓷砖,按尺寸精准开孔并顺手安装到位。
|
||||
橱柜、浴室柜不装挡水条,严控墙面阴阳角垂直度标准。
|
||||
(备注:完整保留原文 10 条监工话术核心细节、施工要求不变,仅微调口语适配口播;每次生成随机打乱 10 条顺序,不固定排序,始终保留每条原意,不篡改施工工艺和细节要求)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:内置 10 条瓦工监工固定要点,每次生成脚本自动随机打乱重新排序,不按原文固定顺序,避免内容重复同质化,适配短视频日更需求。
|
||||
文案调整要求:仅做口语化句式微调,把书面表述改成接地气口播大白话,不改动任何施工细节、工艺要求、禁忌标准,完整保留 10 条话术核心原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 440-480 字,按每秒 4 个纯文字计算,对应时长 110-120s,讲解饱满不拖沓,符合短视频用户完播习惯。
|
||||
内容适配性:打乱顺序后文案衔接自然,每条话术独立成点、逻辑通顺,贴合业主瓦工进场监工刚需,直击无效送礼不如专业话术管用的核心痛点,每一条都明确施工标准和避坑要点。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领资料、评论区扣关键词、福利引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头句式和吐槽语气,3 秒抓眼球,直击业主花钱送礼无效监工的通病,引出专业监工话术。
|
||||
全程口语化大白话,接地气、通俗易懂,站装修业主视角共情讲解,不生硬说教。
|
||||
可微调句式语序,严禁篡改 10 条瓦工监工话术的施工细节、工艺标准、硬性要求,每句带标点规范断句,适配口播节奏,不拆改核心语义。
|
||||
【内置固定原文案】
|
||||
我发现 90% 的业主都在无效监工,又是买水又是买烟又是送吃的。妄想用真情来打动师傅,我只能说你太天真了。要想装修不踩坑,真不如交代这十句话管用。
|
||||
第一句,师傅,我想要入户进门就看到整块砖,然后全屋通铺,把边角料全塞在家具能挡住的地方。
|
||||
第二句,铺贴时遇到有色差、破损的砖请别往上贴,单独放一边。我要找商家退换处理。
|
||||
第三句,卫生间地面我要做坡度,确保地漏是最低点,这样下水才快。另外,地漏不能有断层。
|
||||
第四句,师傅,卫生间的下水管道先贴阻尼片再包隔音棉,然后再砌砖包管子,最后贴瓷砖。
|
||||
第五句,师傅,后期我要装铝合金踢脚线,墙和瓷砖的缝隙别留太大。
|
||||
第六句,师傅,我家卫生间要做单包套,一定要记得给我四周贴砖,不然后期做门又得多花钱。
|
||||
第七句,师傅出水口一定要帮我做下密封处理,省得以后渗水。
|
||||
第八句,师傅,所有的转角都要海棠角,后期我要做美缝,千万别给我做阳角条。
|
||||
第九句,师傅需要贴止逆阀的地方一定要帮我贴一块整砖。我的止逆阀也买回来,你按这个开孔以后,顺手帮我装上吧。
|
||||
第十句,师傅,我家橱柜和浴室柜不打算装挡水条,所以对墙面阴阳角的垂直度要求比较高,麻烦你上点心啊。
|
||||
准备新房装修的朋友,我整理了装修全流程避坑手册。评论区抠避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓦工铺贴、监工话术主题,优先选贴砖恶搞、瓷砖铺贴、墙面空鼓等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、瓷砖开孔、墙面基层、水电验收等贴合瓦工监工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修瓦工进场、不懂专业监工、只会送礼讨好师傅、想靠专业话术把控施工细节的装修业主,围绕瓦工施工 10 句必备监工话术创作,每次生成随机打乱 10 条话术顺序重新编排,保留原意不变。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 随机打乱 10 条瓦工监工话术 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,用接地气吐槽语气点出业主无效监工痛点,引出下文 10 句监工话术。
|
||||
中间核心(瓦工施工 10 句监工重点话术,文案可适当微调句式、口语化优化,保留每条原意不变,每次生成自动随机打乱重新编排顺序):
|
||||
入户瓷砖优先铺整块,全屋通铺,边角料藏在家具遮挡位置。
|
||||
有色差、破损瑕疵瓷砖不要铺贴,单独放置留作商家退换。
|
||||
卫生间地面做好排水坡度,地漏做最低点,管道铺贴无断层。
|
||||
卫生间下水管道先贴阻尼片、包隔音棉,再砌砖贴砖做好隔音。
|
||||
后期装铝合金踢脚线,提前把控墙面与瓷砖预留缝隙大小。
|
||||
卫生间做单包套,四周必须完整贴砖,避免后期额外增项花钱。
|
||||
墙面出水口做好密封处理,从源头杜绝后期墙面渗水隐患。
|
||||
瓷砖转角统一做海棠角,预留美缝空间,禁止加装阳角条。
|
||||
止逆阀位置铺贴整块瓷砖,按尺寸精准开孔并顺手安装到位。
|
||||
橱柜、浴室柜不装挡水条,严控墙面阴阳角垂直度标准。
|
||||
(备注:完整保留原文 10 条监工话术核心细节、施工要求不变,仅微调口语适配口播;每次生成随机打乱 10 条顺序,不固定排序,始终保留每条原意,不篡改施工工艺和细节要求)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:内置 10 条瓦工监工固定要点,每次生成脚本自动随机打乱重新排序,不按原文固定顺序,避免内容重复同质化,适配短视频日更需求。
|
||||
文案调整要求:仅做口语化句式微调,把书面表述改成接地气口播大白话,不改动任何施工细节、工艺要求、禁忌标准,完整保留 10 条话术核心原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 440-480 字,按每秒 4 个纯文字计算,对应时长 110-120s,讲解饱满不拖沓,符合短视频用户完播习惯。
|
||||
内容适配性:打乱顺序后文案衔接自然,每条话术独立成点、逻辑通顺,贴合业主瓦工进场监工刚需,直击无效送礼不如专业话术管用的核心痛点,每一条都明确施工标准和避坑要点。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领资料、评论区回复关键词、福利引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头句式和吐槽语气,3 秒抓眼球,直击业主花钱送礼无效监工的通病,引出专业监工话术。
|
||||
全程口语化大白话,接地气、通俗易懂,站装修业主视角共情讲解,不生硬说教。
|
||||
可微调句式语序,严禁篡改 10 条瓦工监工话术的施工细节、工艺标准、硬性要求,每句带标点规范断句,适配口播节奏,不拆改核心语义。
|
||||
【内置固定原文案】
|
||||
我发现 90% 的业主都在无效监工,又是买水又是买烟又是送吃的。妄想用真情来打动师傅,我只能说你太天真了。要想装修不踩坑,真不如交代这十句话管用。
|
||||
第一句,师傅,我想要入户进门就看到整块砖,然后全屋通铺,把边角料全塞在家具能挡住的地方。
|
||||
第二句,铺贴时遇到有色差、破损的砖请别往上贴,单独放一边。我要找商家退换处理。
|
||||
第三句,卫生间地面我要做坡度,确保地漏是最低点,这样下水才快。另外,地漏不能有断层。
|
||||
第四句,师傅,卫生间的下水管道先贴阻尼片再包隔音棉,然后再砌砖包管子,最后贴瓷砖。
|
||||
第五句,师傅,后期我要装铝合金踢脚线,墙和瓷砖的缝隙别留太大。
|
||||
第六句,师傅,我家卫生间要做单包套,一定要记得给我四周贴砖,不然后期做门又得多花钱。
|
||||
第七句,师傅出水口一定要帮我做下密封处理,省得以后渗水。
|
||||
第八句,师傅,所有的转角都要海棠角,后期我要做美缝,千万别给我做阳角条。
|
||||
第九句,师傅需要贴止逆阀的地方一定要帮我贴一块整砖。我的止逆阀也买回来,你按这个开孔以后,顺手帮我装上吧。
|
||||
第十句,师傅,我家橱柜和浴室柜不打算装挡水条,所以对墙面阴阳角的垂直度要求比较高,麻烦你上点心啊。
|
||||
准备新房装修的朋友,我整理了装修全流程避坑手册。评论区回复避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓦工铺贴、监工话术主题,优先选贴砖恶搞、瓷砖铺贴、墙面空鼓等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、瓷砖开孔、墙面基层、水电验收等贴合瓦工监工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
@@ -1,260 +1,260 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将迎来瓦工进场、担心瓦工施工糊弄、后期瓷砖出现空鼓、开裂、脱落等问题的业主,严格围绕瓦工进场施工避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 7个瓦工施工避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:瓦工进场】,谁要是满脑子只想着【错误操作:做海棠角、全屋通铺墙壁对缝】,你就直接【拒绝动作:别只盯着这些】。你以为他是帮你【表面好处:做美观、显工艺】,其实他就是图【错误目的:糊弄你、省事儿】。下面这7个细节一定要看仔细,少看一条都可能亏几万!”为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(7个瓦工进场避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
1. 瓷砖排版:瓷砖排版别让瓦工来做,买砖的时候让商家设计师免费给你排好版。瓦工手艺再好,也比不过电脑精准,进场时让师傅拿着图纸现场复核一遍,没问题再施工。
|
||||
2. 瓷砖筛选:交代师傅有色差和瑕疵的砖不能贴,一定要挑出来找商家换货,还要检查瓷砖背面有没有脱墨剂,这玩意儿会严重降低瓷砖粘性,导致瓷砖脱落,必须清理干净才能贴。
|
||||
3. 贴砖方向:贴砖时让师傅按砖背面的箭头方向来贴,不然贴完瓷砖表面光泽不一致,一块深一块浅,丑得没法看,后期想改都要砸砖返工。
|
||||
4. 抗裂处理:新旧墙体交接处、烟道位置,记得让师傅挂钢丝网,抹上抗裂砂浆再贴砖,不然季节交替热胀冷缩,这里的砖很容易空鼓、脱落。
|
||||
5. 瓷砖开孔:所有需要开孔的瓷砖,必须用专业开孔器来开,保证开孔规整,不然后期瓷砖很容易从开口处开裂,影响美观还存在安全隐患。
|
||||
6. 卫生间回填:卫生间千万不要用建筑垃圾回填,让师傅用陶粒回填,陶粒质轻还吸水,回填完再铺一层钢筋网,加水泥找平,才能保证后期地面不下沉。
|
||||
7. 后期保护:师傅贴完砖以后要及时清缝,后期美缝才不会崩瓷,还要用厚纸板把地砖盖好,做好成品保护,避免后期施工造成刮痕。
|
||||
(备注:保留原文7个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当调整句式让口语化更贴合口播)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑手续】,抠【核心关键词:避坑】直接拿走!”
|
||||
【开篇&语言要求】
|
||||
开篇钩子,直击瓦工施工糊弄、后期瓷砖出问题的痛点,3秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文中瓦工施工的核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
瓦工进场,如果你满脑子只有做海棠角,全屋通铺墙壁对缝,那你后面肯定要踩大坑。瓦工一来,你先交代好这7个细节,师傅听了就不敢糊弄你。
|
||||
第一,瓷砖不需要瓦工排版,买砖的时候让商家设计师免费给你排好版。瓦工手艺再好,也比不过电脑精准。进场时,让师傅拿着图纸现场复核一遍,没问题再施工。
|
||||
第二,交代师傅有色差和瑕疵的砖不能贴,一定要挑出来找商家换货,还要检查瓷砖背面有没有脱墨剂。这玩意儿会严重降低瓷砖的粘性,导致瓷砖往下掉。必须清理干净才能贴。
|
||||
第三,贴砖的时候,让师傅按砖背面的箭头方向来贴,不然贴完表面光泽不一样,一块儿深一块儿浅,丑的没法看。
|
||||
第四,新旧墙体交接处、烟道位置记得让师傅挂钢丝网,抹上抗裂砂浆再贴砖,不然季节交替,热胀冷缩,这里的砖很容易空鼓脱落。
|
||||
第五,所有需要开孔的瓷砖必须用专业开孔器来开,保证开孔规整,不然后期瓷砖很容易从开口处开裂。
|
||||
第六,卫生间千万不要用建筑垃圾回填,让师傅用陶粒回填,陶粒轻还吸水。回填完再铺一层钢筋网,加水泥找平,才能保证后期地面不下沉。
|
||||
第七,师傅贴完砖以后要及时清缝,后期美缝才不会崩瓷,还要用厚纸板把地砖盖好,做好保护,避免后期施工造成刮痕。
|
||||
准备新房装修的朋友,我整理了一份装修全流程避坑手续。抠避坑,直接拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓦工主题,优先选贴砖恶搞、墙面空鼓、瓷砖开裂等相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、瓷砖开孔、陶粒回填等贴合瓦工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离400–480(含数字,不含标点符号)、总时长偏离100–120秒。
|
||||
禁止篡改原文瓦工避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角、通缝,后期必踩大坑”,
|
||||
“duration”: “4.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “先交代这7个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “4.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “第一,瓷砖排版别让瓦工做,商家设计师免费排更精准。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将迎来瓦工进场、担心瓦工施工糊弄、后期瓷砖出现空鼓、开裂、脱落等问题的业主,严格围绕瓦工进场施工避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 7个瓦工施工避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:瓦工进场】,谁要是满脑子只想着【错误操作:做海棠角、全屋通铺墙壁对缝】,你就直接【拒绝动作:别只盯着这些】。你以为他是帮你【表面好处:做美观、显工艺】,其实他就是图【错误目的:糊弄你、省事儿】。下面这7个细节一定要看仔细,少看一条都可能亏几万!”为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(7个瓦工进场避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
1. 瓷砖排版:瓷砖排版别让瓦工来做,买砖的时候让商家设计师免费给你排好版。瓦工手艺再好,也比不过电脑精准,进场时让师傅拿着图纸现场复核一遍,没问题再施工。
|
||||
2. 瓷砖筛选:交代师傅有色差和瑕疵的砖不能贴,一定要挑出来找商家换货,还要检查瓷砖背面有没有脱墨剂,这玩意儿会严重降低瓷砖粘性,导致瓷砖脱落,必须清理干净才能贴。
|
||||
3. 贴砖方向:贴砖时让师傅按砖背面的箭头方向来贴,不然贴完瓷砖表面光泽不一致,一块深一块浅,丑得没法看,后期想改都要砸砖返工。
|
||||
4. 抗裂处理:新旧墙体交接处、烟道位置,记得让师傅挂钢丝网,抹上抗裂砂浆再贴砖,不然季节交替热胀冷缩,这里的砖很容易空鼓、脱落。
|
||||
5. 瓷砖开孔:所有需要开孔的瓷砖,必须用专业开孔器来开,保证开孔规整,不然后期瓷砖很容易从开口处开裂,影响美观还存在安全隐患。
|
||||
6. 卫生间回填:卫生间千万不要用建筑垃圾回填,让师傅用陶粒回填,陶粒质轻还吸水,回填完再铺一层钢筋网,加水泥找平,才能保证后期地面不下沉。
|
||||
7. 后期保护:师傅贴完砖以后要及时清缝,后期美缝才不会崩瓷,还要用厚纸板把地砖盖好,做好成品保护,避免后期施工造成刮痕。
|
||||
(备注:保留原文7个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当调整句式让口语化更贴合口播)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑手续】,回复【核心关键词:避坑】直接拿走!”
|
||||
【开篇&语言要求】
|
||||
开篇钩子,直击瓦工施工糊弄、后期瓷砖出问题的痛点,3秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文中瓦工施工的核心细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
瓦工进场,如果你满脑子只有做海棠角,全屋通铺墙壁对缝,那你后面肯定要踩大坑。瓦工一来,你先交代好这7个细节,师傅听了就不敢糊弄你。
|
||||
第一,瓷砖不需要瓦工排版,买砖的时候让商家设计师免费给你排好版。瓦工手艺再好,也比不过电脑精准。进场时,让师傅拿着图纸现场复核一遍,没问题再施工。
|
||||
第二,交代师傅有色差和瑕疵的砖不能贴,一定要挑出来找商家换货,还要检查瓷砖背面有没有脱墨剂。这玩意儿会严重降低瓷砖的粘性,导致瓷砖往下掉。必须清理干净才能贴。
|
||||
第三,贴砖的时候,让师傅按砖背面的箭头方向来贴,不然贴完表面光泽不一样,一块儿深一块儿浅,丑的没法看。
|
||||
第四,新旧墙体交接处、烟道位置记得让师傅挂钢丝网,抹上抗裂砂浆再贴砖,不然季节交替,热胀冷缩,这里的砖很容易空鼓脱落。
|
||||
第五,所有需要开孔的瓷砖必须用专业开孔器来开,保证开孔规整,不然后期瓷砖很容易从开口处开裂。
|
||||
第六,卫生间千万不要用建筑垃圾回填,让师傅用陶粒回填,陶粒轻还吸水。回填完再铺一层钢筋网,加水泥找平,才能保证后期地面不下沉。
|
||||
第七,师傅贴完砖以后要及时清缝,后期美缝才不会崩瓷,还要用厚纸板把地砖盖好,做好保护,避免后期施工造成刮痕。
|
||||
准备新房装修的朋友,我整理了一份装修全流程避坑手续。回复避坑,直接拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓦工主题,优先选贴砖恶搞、墙面空鼓、瓷砖开裂等相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、瓷砖开孔、陶粒回填等贴合瓦工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离400–480(含数字,不含标点符号)、总时长偏离100–120秒。
|
||||
禁止篡改原文瓦工避坑相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角、通缝,后期必踩大坑”,
|
||||
“duration”: “4.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “先交代这7个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “4.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “第一,瓷砖排版别让瓦工做,商家设计师免费排更精准。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
]
|
||||
@@ -1,259 +1,259 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:瓷砖刚铺贴完成、被装修公司催促赶工期、不懂停工注意事项、容易提前施工留下后期隐患的装修业主,围绕瓷砖铺贴后5件必停必等事项创作,按原文序号排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 5个瓷砖铺贴停工避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“瓷砖铺完后必须要停工几天,哪怕是装修公司催,下面这5件事也别着急着干,不然后期出问题,责任全是你自己的。”为核心句式,用警示性语气点出常见坑,引出下文5个要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(5个瓷砖铺贴停工避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
1. 瓦工验收:瓦工结束后不能立马验收。装修公司这时候拿个空鼓锤来,就是忽悠你不懂。你要是签字了,后期有问题就是你的责任了。这里一定要等水泥砂浆干透了,才能验出来是否空鼓,最起码要等五六天左右。
|
||||
2. 美缝施工:美缝不能在瓷砖刚铺完就做,要等一周左右,等缝隙里面的水迹干透了,检查有没有空鼓了再做美缝。不然后期出现了反碱脱落,后续维权麻烦不说,还得返工耗费时间金钱。
|
||||
3. 瓷砖养护:瓷砖铺完后千万不要洒水,你洒水养护的是下面的水泥砂浆,那活儿,瓦工铺的时候就应该把墙面地面打湿再贴,铺完了再打扫干净,盖好保护膜就可以了,别多此一举。
|
||||
4. 标识保留:墙面的水电标识贴不要撕,这是给后期安装师傅看的。你一撕,人家打孔打到水管电线,不仅维修麻烦,还可能造成安全隐患,得不偿失。
|
||||
5. 停工利用:停工这几天也别闲着。闲着你就可以让定制商家上门复尺,提前下单,定制周期差不多一个月,到时候你家油工结束了,这些东西正好能装,一点儿不耽误工期。
|
||||
(备注:保留原文5个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当调整句式让口语化更贴合口播,补充美缝反碱、水电标识撕毁的危害,贴合搜索参考内容)
|
||||
### 中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
1. 排序逻辑:严格按原文5个要点的序号排列,不随机抽取、不打乱顺序,保证内容连贯性,贴合业主瓷砖铺贴后停工的实际流程,从验收、施工、养护、标识到工期利用,层层递进,符合业主认知逻辑。
|
||||
2. 文案调整要求:微调仅针对句式口语化优化,比如将书面化表述改为抖音/视频号口播常用的接地气语气,补充轻微危害提示(结合美缝反碱脱落、水电标识撕毁的隐患),不改变每个坑的核心信息——如验收等待五六天、美缝等待一周、禁止洒水、保留水电标识、定制复尺周期一个月等核心时间节点和禁忌,所有细节完全保留,贴合原文原意。
|
||||
3. 字数与时长控制:纯文字+数字(扣除标点)严格控制在400-480字,按每秒4个纯文字计算,对应时长100-120s,既保证每个避坑点讲解透彻,补充必要危害提示,又不拖沓,符合短视频用户观看习惯,避免用户划走。
|
||||
4. 内容适配性:5个避坑要点讲解时需衔接自然,每个坑独立成段(分镜对应空镜),不重复、不冗余,重点突出“停工避坑”核心,贴合业主担心被装修公司催促、怕后期出问题自己担责、想合理利用停工时间的核心痛点,每段讲解都紧扣“为什么不能做、怎么做才对”的逻辑,与原文保持一致,结合参考内容完善危害提示,增强说服力。
|
||||
结尾范式:以“如果你们也在准备新房装修,不知道还有哪些坑要避,评论区扣 ‘装修’,我把整理好的装修避坑手册,免费发给你们,帮你们省时间、省钱!记得关注我,装修不踩坑!”为核心句式,保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动领福利、评论区扣关键词、关注引导的核心逻辑。
|
||||
【开篇&语言要求】
|
||||
开篇严格遵循核心强制规则的警示性句式,3秒抓眼球不拖沓,用犀利语气点出瓷砖铺贴后被催工期、盲目施工后期担责的痛点,贴合装修业主避坑需求,不偏离范式结构。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站业主共情立场,用警示性语气讲解,贴合口播传播特点,增强代入感,补充的危害提示通俗易懂,让业主清晰了解违规操作的后果。
|
||||
可微调句式语序,严禁篡改5个停工避坑要点的核心细节、时间节点、操作规范,每句带标点规范断句,适配口播节奏,避免大长句,同时结合参考内容完善美缝反碱、水电标识相关危害表述。
|
||||
【内置固定原文案】
|
||||
瓷砖铺完后必须要停工几天,哪怕是装修公司催,下面这5件事也别着急着干,不然后期出问题,责任全是你自己的。
|
||||
第一,瓦工结束后不能立马验收。装修公司这时候拿个空鼓锤来,就是忽悠你不懂。你要是签字了,后期有问题就是你的责任了。这里呢,是一定要等水泥砂浆干透了,才能验出来是否空鼓,最起码要等五六天左右。
|
||||
第二,美缝不能在瓷砖刚铺完就做,要等一周左右,等缝隙里面的水迹干透了,检查有没有空鼓了再做美缝。不然后期出现了反碱脱落,你找谁去?毕竟美缝反碱后会形成隔离层,导致粘结不牢固,返工又费钱又费力。
|
||||
第三,瓷砖铺完后千万不要洒水,你洒水养护的是下面的水泥砂浆,那活儿,瓦工铺的时候就应该把墙面地面打湿再贴,铺完了再打扫干净,盖好保护膜就可以了,别多此一举。
|
||||
第四,墙面的水电标识贴不要撕,这是给后期安装师傅看的。你一撕,人家打孔打到水管电线,你就等着哭吧,不仅维修麻烦,还可能引发安全隐患。
|
||||
最后,停工这几天也别闲着。闲着你就可以让定制商家上门复尺,提前下单,定制周期差不多一个月,到时候你家油工结束了,这些东西正好能装,一点儿不耽误工期。
|
||||
如果你们也在准备新房装修,不知道还有哪些坑要避,评论区扣 “装修”,我把整理好的装修避坑手册,免费发给你们,帮你们省时间、省钱!记得关注我,装修不踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓷砖铺贴、停工避坑主题,优先选贴砖恶搞、墙面空鼓、瓷砖铺贴等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、美缝施工、成品保护、水电验收等贴合瓷砖铺贴停工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓦工结束后不能立马验收,至少要等五六天。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “瓷砖铺完别着急复工,这 5 件事做早了全是坑” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “瓷砖铺完别着急复工,这 5 件事做早了全是坑” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "贴砖恶搞 - 恶搞开篇",
|
||||
"voiceover": "瓷砖铺完别着急复工,装修公司催也别理,5 件事必等!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "这些事做早了后期全是坑,责任还得你自己担!",
|
||||
"duration": "5.00s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "瓷砖铺贴 - 瓷砖完工展示",
|
||||
"voiceover": "第一,瓦工结束别立马验收,至少等五六天再验空鼓!",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:瓷砖刚铺贴完成、被装修公司催促赶工期、不懂停工注意事项、容易提前施工留下后期隐患的装修业主,围绕瓷砖铺贴后5件必停必等事项创作,按原文序号排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 5个瓷砖铺贴停工避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“瓷砖铺完后必须要停工几天,哪怕是装修公司催,下面这5件事也别着急着干,不然后期出问题,责任全是你自己的。”为核心句式,用警示性语气点出常见坑,引出下文5个要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(5个瓷砖铺贴停工避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
1. 瓦工验收:瓦工结束后不能立马验收。装修公司这时候拿个空鼓锤来,就是忽悠你不懂。你要是签字了,后期有问题就是你的责任了。这里一定要等水泥砂浆干透了,才能验出来是否空鼓,最起码要等五六天左右。
|
||||
2. 美缝施工:美缝不能在瓷砖刚铺完就做,要等一周左右,等缝隙里面的水迹干透了,检查有没有空鼓了再做美缝。不然后期出现了反碱脱落,后续维权麻烦不说,还得返工耗费时间金钱。
|
||||
3. 瓷砖养护:瓷砖铺完后千万不要洒水,你洒水养护的是下面的水泥砂浆,那活儿,瓦工铺的时候就应该把墙面地面打湿再贴,铺完了再打扫干净,盖好保护膜就可以了,别多此一举。
|
||||
4. 标识保留:墙面的水电标识贴不要撕,这是给后期安装师傅看的。你一撕,人家打孔打到水管电线,不仅维修麻烦,还可能造成安全隐患,得不偿失。
|
||||
5. 停工利用:停工这几天也别闲着。闲着你就可以让定制商家上门复尺,提前下单,定制周期差不多一个月,到时候你家油工结束了,这些东西正好能装,一点儿不耽误工期。
|
||||
(备注:保留原文5个要点,按原文序号排列,保留原文核心细节和避坑逻辑,适当调整句式让口语化更贴合口播,补充美缝反碱、水电标识撕毁的危害,贴合搜索参考内容)
|
||||
### 中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
1. 排序逻辑:严格按原文5个要点的序号排列,不随机抽取、不打乱顺序,保证内容连贯性,贴合业主瓷砖铺贴后停工的实际流程,从验收、施工、养护、标识到工期利用,层层递进,符合业主认知逻辑。
|
||||
2. 文案调整要求:微调仅针对句式口语化优化,比如将书面化表述改为抖音/视频号口播常用的接地气语气,补充轻微危害提示(结合美缝反碱脱落、水电标识撕毁的隐患),不改变每个坑的核心信息——如验收等待五六天、美缝等待一周、禁止洒水、保留水电标识、定制复尺周期一个月等核心时间节点和禁忌,所有细节完全保留,贴合原文原意。
|
||||
3. 字数与时长控制:纯文字+数字(扣除标点)严格控制在400-480字,按每秒4个纯文字计算,对应时长100-120s,既保证每个避坑点讲解透彻,补充必要危害提示,又不拖沓,符合短视频用户观看习惯,避免用户划走。
|
||||
4. 内容适配性:5个避坑要点讲解时需衔接自然,每个坑独立成段(分镜对应空镜),不重复、不冗余,重点突出“停工避坑”核心,贴合业主担心被装修公司催促、怕后期出问题自己担责、想合理利用停工时间的核心痛点,每段讲解都紧扣“为什么不能做、怎么做才对”的逻辑,与原文保持一致,结合参考内容完善危害提示,增强说服力。
|
||||
结尾范式:以“如果你们也在准备新房装修,不知道还有哪些坑要避,评论区回复 ‘装修’,我把整理好的装修避坑手册,免费发给你们,帮你们省时间、省钱!记得关注我,装修不踩坑!”为核心句式,保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动领福利、评论区回复关键词、关注引导的核心逻辑。
|
||||
【开篇&语言要求】
|
||||
开篇严格遵循核心强制规则的警示性句式,3秒抓眼球不拖沓,用犀利语气点出瓷砖铺贴后被催工期、盲目施工后期担责的痛点,贴合装修业主避坑需求,不偏离范式结构。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站业主共情立场,用警示性语气讲解,贴合口播传播特点,增强代入感,补充的危害提示通俗易懂,让业主清晰了解违规操作的后果。
|
||||
可微调句式语序,严禁篡改5个停工避坑要点的核心细节、时间节点、操作规范,每句带标点规范断句,适配口播节奏,避免大长句,同时结合参考内容完善美缝反碱、水电标识相关危害表述。
|
||||
【内置固定原文案】
|
||||
瓷砖铺完后必须要停工几天,哪怕是装修公司催,下面这5件事也别着急着干,不然后期出问题,责任全是你自己的。
|
||||
第一,瓦工结束后不能立马验收。装修公司这时候拿个空鼓锤来,就是忽悠你不懂。你要是签字了,后期有问题就是你的责任了。这里呢,是一定要等水泥砂浆干透了,才能验出来是否空鼓,最起码要等五六天左右。
|
||||
第二,美缝不能在瓷砖刚铺完就做,要等一周左右,等缝隙里面的水迹干透了,检查有没有空鼓了再做美缝。不然后期出现了反碱脱落,你找谁去?毕竟美缝反碱后会形成隔离层,导致粘结不牢固,返工又费钱又费力。
|
||||
第三,瓷砖铺完后千万不要洒水,你洒水养护的是下面的水泥砂浆,那活儿,瓦工铺的时候就应该把墙面地面打湿再贴,铺完了再打扫干净,盖好保护膜就可以了,别多此一举。
|
||||
第四,墙面的水电标识贴不要撕,这是给后期安装师傅看的。你一撕,人家打孔打到水管电线,你就等着哭吧,不仅维修麻烦,还可能引发安全隐患。
|
||||
最后,停工这几天也别闲着。闲着你就可以让定制商家上门复尺,提前下单,定制周期差不多一个月,到时候你家油工结束了,这些东西正好能装,一点儿不耽误工期。
|
||||
如果你们也在准备新房装修,不知道还有哪些坑要避,评论区回复 “装修”,我把整理好的装修避坑手册,免费发给你们,帮你们省时间、省钱!记得关注我,装修不踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近瓷砖铺贴、停工避坑主题,优先选贴砖恶搞、墙面空鼓、瓷砖铺贴等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选瓷砖铺贴、美缝施工、成品保护、水电验收等贴合瓷砖铺贴停工主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓦工结束后不能立马验收,至少要等五六天。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “瓷砖铺完别着急复工,这 5 件事做早了全是坑” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “瓷砖铺完别着急复工,这 5 件事做早了全是坑” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "贴砖恶搞 - 恶搞开篇",
|
||||
"voiceover": "瓷砖铺完别着急复工,装修公司催也别理,5 件事必等!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "这些事做早了后期全是坑,责任还得你自己担!",
|
||||
"duration": "5.00s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "瓷砖铺贴 - 瓷砖完工展示",
|
||||
"voiceover": "第一,瓦工结束别立马验收,至少等五六天再验空鼓!",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
@@ -1,260 +1,260 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、不清楚哪些施工节点必须在场监工,担心师傅偷工减料、后期入住变成甲醛房的业主,严格围绕装修 7 个必在场施工节点避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 7 个装修关键节点避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:全流程施工】,很多业主全程不到场监工,只看重表面装修效果。你以为他是帮你【表面好处:省心、省时间】,其实他就是图【错误目的:偷工减料、糊弄业主】。下面这 7 个在场时间一定要记牢,尤其最后一个关乎是不是甲醛房!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(7 个装修必在场节点要点,文案适当精简调整,意思保持原意,按原文序号排列,不随机抽取):
|
||||
砸墙施工:砸墙阶段务必在场,盯紧师傅封好下水口,避免管道堵塞,后期还要下楼疏通。
|
||||
窗户安装:封窗施工一定要到场,监督做好防水斜坡,杜绝雨天雨水往室内倒灌渗水。
|
||||
水电验收:水电完工验收必须在场,核对开关插座点位,包裹强弱电并拍照留存防返工。
|
||||
防水瓷砖:防水和瓷砖验收要在场,闭水试验排查漏水,核对瓷砖型号避免色差重铺。
|
||||
瓷砖铺贴:贴砖期间现场监督,检查瓷砖平整度、空鼓率,保证阴阳角方正、缝隙均匀。
|
||||
木工吊顶:木工做吊顶务必在场,拐角整板铺设、接缝开 V 型槽,防止后期乳胶漆开裂。
|
||||
腻子施工:刮腻子阶段一定要在场,禁止往腻子里加胶水,避免甲醛超标形成毒气房。
|
||||
(备注:保留原文 7 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,精简句式控制整体字数,贴合口播语感)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全程避坑手册】,抠【核心关键词:避坑】直接拿走!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击装修不懂监工节点、容易被糊弄、住进甲醛房的痛点,3 秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调精简句式,不得篡改原文各施工节点核心监督细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
新房装修一定要在场的 7 个时间,尤其最后一个,直接关系是不是甲醛房!
|
||||
第一,砸墙时必须在场,盯紧师傅封好下水口,不然堵了还要跑楼下疏通。
|
||||
第二,封窗时一定要在场,监督做好防水斜坡,防止下雨天雨水往屋里倒灌。
|
||||
第三,水电验收必须在场,核对点位、查强弱电包裹,记得拍照留存避返工。
|
||||
第四,防水瓷砖验收必在场,闭水试验查漏水,核对瓷砖型号防色差重铺。
|
||||
第五,贴砖时要在场,检查平整度空鼓率,阴阳角方正、缝隙均匀才合格。
|
||||
第六,木工吊顶必在场,拐角整板、接缝做 V 型槽,杜绝后期乳胶漆开裂。
|
||||
第七,刮腻子一定要在场,严禁往腻子加胶水,不然甲醛超标变毒气房。
|
||||
准备装修的朋友,我整理了避坑手册,评论区扣避坑直接领取参考!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修监工主题,优先选工地恶搞、墙体拆除、墙面开裂等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙体拆除、吊顶造型、水电验收、瓷砖铺贴等贴合施工节点主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 240–280(含数字,不含标点符号)、总时长偏离 60–70 秒。
|
||||
禁止篡改原文装修 7 大施工节点监工相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.50s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、不清楚哪些施工节点必须在场监工,担心师傅偷工减料、后期入住变成甲醛房的业主,严格围绕装修 7 个必在场施工节点避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 7 个装修关键节点避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:全流程施工】,很多业主全程不到场监工,只看重表面装修效果。你以为他是帮你【表面好处:省心、省时间】,其实他就是图【错误目的:偷工减料、糊弄业主】。下面这 7 个在场时间一定要记牢,尤其最后一个关乎是不是甲醛房!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(7 个装修必在场节点要点,文案适当精简调整,意思保持原意,按原文序号排列,不随机抽取):
|
||||
砸墙施工:砸墙阶段务必在场,盯紧师傅封好下水口,避免管道堵塞,后期还要下楼疏通。
|
||||
窗户安装:封窗施工一定要到场,监督做好防水斜坡,杜绝雨天雨水往室内倒灌渗水。
|
||||
水电验收:水电完工验收必须在场,核对开关插座点位,包裹强弱电并拍照留存防返工。
|
||||
防水瓷砖:防水和瓷砖验收要在场,闭水试验排查漏水,核对瓷砖型号避免色差重铺。
|
||||
瓷砖铺贴:贴砖期间现场监督,检查瓷砖平整度、空鼓率,保证阴阳角方正、缝隙均匀。
|
||||
木工吊顶:木工做吊顶务必在场,拐角整板铺设、接缝开 V 型槽,防止后期乳胶漆开裂。
|
||||
腻子施工:刮腻子阶段一定要在场,禁止往腻子里加胶水,避免甲醛超标形成毒气房。
|
||||
(备注:保留原文 7 个要点,按原文序号排列,保留原文核心细节和避坑逻辑,精简句式控制整体字数,贴合口播语感)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全程避坑手册】,回复【核心关键词:避坑】直接拿走!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击装修不懂监工节点、容易被糊弄、住进甲醛房的痛点,3 秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调精简句式,不得篡改原文各施工节点核心监督细节和避坑逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
新房装修一定要在场的 7 个时间,尤其最后一个,直接关系是不是甲醛房!
|
||||
第一,砸墙时必须在场,盯紧师傅封好下水口,不然堵了还要跑楼下疏通。
|
||||
第二,封窗时一定要在场,监督做好防水斜坡,防止下雨天雨水往屋里倒灌。
|
||||
第三,水电验收必须在场,核对点位、查强弱电包裹,记得拍照留存避返工。
|
||||
第四,防水瓷砖验收必在场,闭水试验查漏水,核对瓷砖型号防色差重铺。
|
||||
第五,贴砖时要在场,检查平整度空鼓率,阴阳角方正、缝隙均匀才合格。
|
||||
第六,木工吊顶必在场,拐角整板、接缝做 V 型槽,杜绝后期乳胶漆开裂。
|
||||
第七,刮腻子一定要在场,严禁往腻子加胶水,不然甲醛超标变毒气房。
|
||||
准备装修的朋友,我整理了避坑手册,评论区回复避坑直接领取参考!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修监工主题,优先选工地恶搞、墙体拆除、墙面开裂等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙体拆除、吊顶造型、水电验收、瓷砖铺贴等贴合施工节点主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓷砖排版别让瓦工来做,商家设计师免费排版更精准。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 240–280(含数字,不含标点符号)、总时长偏离 60–70 秒。
|
||||
禁止篡改原文装修 7 大施工节点监工相关的核心细节和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.50s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
]
|
||||
@@ -1,177 +1,177 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:硬装刚完工、不懂软装进场前后收尾细节、着急搬家具入住容易遗留隐患,后期发霉反味、墙面破损难修补的装修业主,围绕硬装结束必做 7 个收尾关键要点创作,按原意逻辑编排,可适度口语微调保留原意。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头硬装收尾痛点引入 + 6 个收尾避坑干货 + 结尾避坑手册引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用警示现实视角点出硬装刚完工别急着进软装,忽略 7 个收尾细节入住容易留隐患、生活闹心吵架的痛点,引出下文 6 个必做收尾关键点。
|
||||
中间核心(硬装完工 6 个收尾避坑要点,文案适当调整修改,意思保持原意,保留原有先后逻辑,不随机打乱,可口语顺滑润色):
|
||||
瓷砖除蜡:亮光砖、柔光砖在家具进场前,一定要用瓷砖除蜡剂全屋拖洗一遍,避免表层蜡质残留,入住后地面发蒙有水雾感,看着别扭难打理。
|
||||
柜体防护:餐边柜、橱柜吊柜底部贴静电防水膜,阻隔水汽熏坏柜体;橱柜内部铺贴铝箔纸,提升防潮效果,日常清洁打理更省心。
|
||||
地漏整改:逐一检查全屋地漏是否存在断层,有断层及时加装加长地漏芯,防止渗水进入砂浆层,避免后期反味、墙面起皮发霉等遗留隐患。
|
||||
全屋打胶:家具进场前提前做全屋精细打胶,重点处理踢脚线底部、厨卫窗框与瓷砖交接位置,优先用美容胶,不建议用美缝剂,避免材质过硬后期脱落开裂。
|
||||
止逆阀对接:检查油烟机、卫生间浴霸和排风扇,确认排风管与止逆阀规范连接,杜绝师傅偷懒随意摆放管路,防止后期全屋倒灌异味。
|
||||
原漆留存:乳胶漆完工后预留未兑水原装漆,密封保存备用,后期装门、装柜体出现磕碰掉漆,可随时修补还原,不用整体返工刷漆。
|
||||
(备注:保留原文 7 个收尾要点的核心细节、施工逻辑、隐患后果不变,适当调整句式让口语化更贴合口播,不篡改工艺做法、选材建议、遗留隐患的核心逻辑)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文 6 大收尾要点顺序排列,不打乱结构,贴合硬装完工到软装进场的真实施工流程,层层递进符合业主装修收尾认知逻辑。
|
||||
文案调整要求:微调仅针对句式口语化优化,把直白叙述话术改成抖音口播接地气大白话,不改变每一步施工做法、选材建议、隐患危害等所有核心信息,完整保留原文原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 440-480 字,按每秒 4 个纯文字计算,对应时长 110-120s,讲解收尾细节细致不啰嗦,节奏适中,适配短视频完播率。
|
||||
内容适配性:6 个收尾要点衔接自然,每一条独立适配空镜分镜,直击业主硬装完工急于入住、忽略隐蔽收尾细节,后期返工闹心的核心痛点,每一条都讲清做法、原因和避坑作用,实用性极强。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修全流程避坑手册、评论区扣关键词引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文警示吐槽语气,3 秒抓眼球,点破硬装刚结束着急搬软装、忽略收尾细节入住就留隐患闹矛盾的真实痛点,瞬间引发装修完工业主共鸣。
|
||||
全程口语化大白话,通俗易懂、接地气,站业主立场拆解装修收尾细节,条理清晰、干货满满,不生硬说教,适配口播传播节奏。
|
||||
可微调句式语序,严禁篡改每一个收尾步骤的施工要求、选材建议、隐患后果等核心内容,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
装修千万别硬装刚结束就急着把沙发、床这些软装搬进去。先把下面这 6 个收尾的活安排明白,要不然等你人入住进去以后,两口子天天吵架。
|
||||
第一,不管你家是亮光砖还是柔光砖,趁家具还没进场,赶紧网购一瓶瓷砖除蜡剂,把地面彻底拖一遍。不然等你住进去,地面怎么都像蒙了一层水雾,看着就闹心。
|
||||
第二,餐边柜和橱柜吊柜底部建议贴一层静电防水膜,防止水蒸气慢慢把咱家的吊柜熏坏了。再有就是橱柜里边贴上铝箔纸,它防潮性会更好,而且更好打理卫生。
|
||||
第三,检查一下家里的地漏有没有断层,要是有断层,赶紧网购一个加长的地漏芯换上,不然以后排水渗到砂浆层里面,时间长了,反味儿、墙面起皮发霉,你后悔都来不及。
|
||||
第四,家具进场前一定要先安排全屋打胶,别自己打,你打不明白。尤其是你的踢脚线底下,以及厨房和卫生间窗框和瓷砖的交界处,一定记得打美容胶,别用美缝剂,美缝剂偏硬,时间长了容易脱落。
|
||||
第五,烟机和卫生间的浴霸、排风扇,你要看它有没有跟止逆阀连接。有很多安装师傅图省事儿,把排风管顺手往顶上一扔,反正你也看不着,后期全是味儿。
|
||||
第六,乳胶漆施工后记得留一些未兑水的原漆,装在密封瓶里保存,后期安装门、柜体时难免磕碰,方便随时修补。
|
||||
记不住的,我都整理在这份装修全流程避坑手册里了。评论扣避坑,拿好少踩坑。
|
||||
【内置完整素材库标题】
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
踢脚线安装验收-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近硬装收尾、软装进场、装修细节避坑主题,优先选工地恶搞、墙面空鼓、硬装完工全屋全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选美缝开荒、成品保护、收尾细节、瓷砖铺贴等贴合硬装收尾避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 “等于” 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 “分镜时长” 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 “分镜文案” 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 “配音文案” 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 “5.25s”)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “防水翻车漏水”,
|
||||
“voiceover”: “新房装修刷防水,一上来就开刷的工人,直接撵走别客气!”,
|
||||
“duration”: “5.75s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “他不是在赶工期,只是在图省事,这 4 点一定要做好。”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “卫生间基层清理 - 防水施工”,
|
||||
“voiceover”: “第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:硬装刚完工、不懂软装进场前后收尾细节、着急搬家具入住容易遗留隐患,后期发霉反味、墙面破损难修补的装修业主,围绕硬装结束必做 7 个收尾关键要点创作,按原意逻辑编排,可适度口语微调保留原意。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头硬装收尾痛点引入 + 6 个收尾避坑干货 + 结尾避坑手册引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用警示现实视角点出硬装刚完工别急着进软装,忽略 7 个收尾细节入住容易留隐患、生活闹心吵架的痛点,引出下文 6 个必做收尾关键点。
|
||||
中间核心(硬装完工 6 个收尾避坑要点,文案适当调整修改,意思保持原意,保留原有先后逻辑,不随机打乱,可口语顺滑润色):
|
||||
瓷砖除蜡:亮光砖、柔光砖在家具进场前,一定要用瓷砖除蜡剂全屋拖洗一遍,避免表层蜡质残留,入住后地面发蒙有水雾感,看着别扭难打理。
|
||||
柜体防护:餐边柜、橱柜吊柜底部贴静电防水膜,阻隔水汽熏坏柜体;橱柜内部铺贴铝箔纸,提升防潮效果,日常清洁打理更省心。
|
||||
地漏整改:逐一检查全屋地漏是否存在断层,有断层及时加装加长地漏芯,防止渗水进入砂浆层,避免后期反味、墙面起皮发霉等遗留隐患。
|
||||
全屋打胶:家具进场前提前做全屋精细打胶,重点处理踢脚线底部、厨卫窗框与瓷砖交接位置,优先用美容胶,不建议用美缝剂,避免材质过硬后期脱落开裂。
|
||||
止逆阀对接:检查油烟机、卫生间浴霸和排风扇,确认排风管与止逆阀规范连接,杜绝师傅偷懒随意摆放管路,防止后期全屋倒灌异味。
|
||||
原漆留存:乳胶漆完工后预留未兑水原装漆,密封保存备用,后期装门、装柜体出现磕碰掉漆,可随时修补还原,不用整体返工刷漆。
|
||||
(备注:保留原文 7 个收尾要点的核心细节、施工逻辑、隐患后果不变,适当调整句式让口语化更贴合口播,不篡改工艺做法、选材建议、遗留隐患的核心逻辑)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文 6 大收尾要点顺序排列,不打乱结构,贴合硬装完工到软装进场的真实施工流程,层层递进符合业主装修收尾认知逻辑。
|
||||
文案调整要求:微调仅针对句式口语化优化,把直白叙述话术改成抖音口播接地气大白话,不改变每一步施工做法、选材建议、隐患危害等所有核心信息,完整保留原文原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 440-480 字,按每秒 4 个纯文字计算,对应时长 110-120s,讲解收尾细节细致不啰嗦,节奏适中,适配短视频完播率。
|
||||
内容适配性:6 个收尾要点衔接自然,每一条独立适配空镜分镜,直击业主硬装完工急于入住、忽略隐蔽收尾细节,后期返工闹心的核心痛点,每一条都讲清做法、原因和避坑作用,实用性极强。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修全流程避坑手册、评论区回复关键词引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文警示吐槽语气,3 秒抓眼球,点破硬装刚结束着急搬软装、忽略收尾细节入住就留隐患闹矛盾的真实痛点,瞬间引发装修完工业主共鸣。
|
||||
全程口语化大白话,通俗易懂、接地气,站业主立场拆解装修收尾细节,条理清晰、干货满满,不生硬说教,适配口播传播节奏。
|
||||
可微调句式语序,严禁篡改每一个收尾步骤的施工要求、选材建议、隐患后果等核心内容,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
装修千万别硬装刚结束就急着把沙发、床这些软装搬进去。先把下面这 6 个收尾的活安排明白,要不然等你人入住进去以后,两口子天天吵架。
|
||||
第一,不管你家是亮光砖还是柔光砖,趁家具还没进场,赶紧网购一瓶瓷砖除蜡剂,把地面彻底拖一遍。不然等你住进去,地面怎么都像蒙了一层水雾,看着就闹心。
|
||||
第二,餐边柜和橱柜吊柜底部建议贴一层静电防水膜,防止水蒸气慢慢把咱家的吊柜熏坏了。再有就是橱柜里边贴上铝箔纸,它防潮性会更好,而且更好打理卫生。
|
||||
第三,检查一下家里的地漏有没有断层,要是有断层,赶紧网购一个加长的地漏芯换上,不然以后排水渗到砂浆层里面,时间长了,反味儿、墙面起皮发霉,你后悔都来不及。
|
||||
第四,家具进场前一定要先安排全屋打胶,别自己打,你打不明白。尤其是你的踢脚线底下,以及厨房和卫生间窗框和瓷砖的交界处,一定记得打美容胶,别用美缝剂,美缝剂偏硬,时间长了容易脱落。
|
||||
第五,烟机和卫生间的浴霸、排风扇,你要看它有没有跟止逆阀连接。有很多安装师傅图省事儿,把排风管顺手往顶上一扔,反正你也看不着,后期全是味儿。
|
||||
第六,乳胶漆施工后记得留一些未兑水的原漆,装在密封瓶里保存,后期安装门、柜体时难免磕碰,方便随时修补。
|
||||
记不住的,我都整理在这份装修全流程避坑手册里了。评论回复避坑,拿好少踩坑。
|
||||
【内置完整素材库标题】
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
踢脚线安装验收-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近硬装收尾、软装进场、装修细节避坑主题,优先选工地恶搞、墙面空鼓、硬装完工全屋全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选美缝开荒、成品保护、收尾细节、瓷砖铺贴等贴合硬装收尾避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 “等于” 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 “分镜时长” 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 “分镜文案” 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 “配音文案” 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 “5.25s”)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “防水翻车漏水”,
|
||||
“voiceover”: “新房装修刷防水,一上来就开刷的工人,直接撵走别客气!”,
|
||||
“duration”: “5.75s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “他不是在赶工期,只是在图省事,这 4 点一定要做好。”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “卫生间基层清理 - 防水施工”,
|
||||
“voiceover”: “第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
]
|
||||
@@ -1,261 +1,261 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修不懂行、过度干预施工细节、盲目给师傅加工序添工作量的装修业主,围绕装修师傅最讨厌业主做的 6 件事创作,按原文序号排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 6 件业主易踩坑行为干货 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “装修师傅最讨厌业主干的 6 件事,尤其是最后一点。” 为核心句式,用警示吐槽语气点出行业真实痛点,引出下文 6 个要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6 件装修师傅反感业主行为要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
水电进场就要求全部转角做大弧弯,水流虽变大,却无形中增加师傅材料与施工成本。
|
||||
水电没完工就提前备好阻尼片、隔音棉,强行要求包厨卫下水管道,给师傅额外增加施工量。
|
||||
防水施工前执意铲掉开发商原有防水、清扫基层,虽能杜绝后期起皮开裂,却耽误师傅一整天工期。
|
||||
木工进场要求所有接缝做 V 型槽、转角做 T 字型,虽能降低墙面开裂概率,却给师傅平添大量工序。
|
||||
瓦工施工时要求卫生间先找坡度、做回形地漏,下水快又美观,但要耗费师傅半天时间重新找平。
|
||||
瓦工未完工就提前买好地漏、止逆阀,强制要求一并安装,直接断了后期安装师傅的额外收入。
|
||||
(备注:保留原文 6 个要点,按原文序号排列,保留原文核心细节和逻辑,适当调整句式让口语化更贴合口播,不篡改每层背后的利弊关系)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文 6 个要点的序号排列,不随机抽取、不打乱顺序,保证内容连贯性,贴合家装从水电、防水、木工到瓦工的施工流程,层层递进符合业主认知。
|
||||
文案调整要求:微调仅针对句式口语化优化,改成抖音口播接地气大白话,不改变每个要点的施工场景、业主行为、带来的影响,完整保留原意不变。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解饱满不拖沓,符合短视频完播习惯。
|
||||
内容适配性:6 个要点讲解衔接自然,每点独立成段适配空镜分镜,聚焦业主不懂行乱指挥、盲目加活的通病,既讲做法又讲背后利弊,真实接地气、容易引发共鸣。
|
||||
结尾范式:以 “如果你也准备新房装修,我整理了一份装修全流程避坑手册。评论区抠避坑,拿去用。” 为核心句式,保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇严格遵循核心强制规则原句,3 秒抓眼球不拖沓,用真实行业视角吐槽业主盲目干预施工的通病,贴合装修受众共情点,不偏离范式结构。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站客观中立角度讲解,语气接地气有真实感,贴合口播传播特点。
|
||||
可微调句式语序,严禁篡改 6 个要点的施工场景、业主行为、利弊细节,每句带标点规范断句,适配口播节奏,避免大长句。
|
||||
【内置固定原文案】
|
||||
装修师傅最讨厌业主干的 6 件事,尤其是最后一点。
|
||||
第一,水电材料刚进场,就要求师傅所有的转角全部用大弧弯,你不提师傅全用直角弯,你洗澡时倒是水流更大了,又给装修师傅增加成本。
|
||||
第二,水电还没完工,你就提前买好了黄金蜂窝阻尼片和隔音棉,非要包卫生间和阳台的下水管道,说这样不会被楼上的出水噪音吵醒,但师傅又多了些活儿。
|
||||
第三,防水师傅刚准备动手刷防水涂料,业主就喊停,让师傅把开发商原有的防水全部铲掉,再把地面打扫干净。说这样防水才不会起皮开裂。你家卫生间倒是不漏水了,做这两样活儿又要耽误师傅一天工期。
|
||||
第四,木工师傅高高兴兴来了,你却告诉他,所有接缝处都要做 V 字型槽,转角处要做到 T 字型。师傅一听就知道你是懂行的。后期墙面是不容易开裂了,又给师傅增加好多活儿。
|
||||
第五,瓦工师傅来了,懂行的业主要求把卫生间先找坡度,地漏做成回形地漏,这样不仅下水快,还好看,可这又得浪费师傅半天时间,重新找坡度。
|
||||
第六,瓦工还没结束,部分业主已经提前买好了地漏和油烟止逆阀,要求师傅一并装上。这下好了,之后安装电器的师傅想赚点外快都不行。
|
||||
如果你也准备新房装修,我整理了一份装修全流程避坑手册。评论区抠避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修施工、业主干预工序主题,优先选贴砖恶搞、墙面空鼓、水电施工等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选水电施工、防水施工、木作基层、瓷砖铺贴等贴合家装全流程主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓦工结束后不能立马验收,至少要等五六天。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “装修师傅最讨厌业主 6 件事,千万别乱干预施工” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:新房装修不懂行、过度干预施工细节、盲目给师傅加工序添工作量的装修业主,围绕装修师傅最讨厌业主做的 6 件事创作,按原文序号排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点引入 + 6 件业主易踩坑行为干货 + 结尾福利引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “装修师傅最讨厌业主干的 6 件事,尤其是最后一点。” 为核心句式,用警示吐槽语气点出行业真实痛点,引出下文 6 个要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6 件装修师傅反感业主行为要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
水电进场就要求全部转角做大弧弯,水流虽变大,却无形中增加师傅材料与施工成本。
|
||||
水电没完工就提前备好阻尼片、隔音棉,强行要求包厨卫下水管道,给师傅额外增加施工量。
|
||||
防水施工前执意铲掉开发商原有防水、清扫基层,虽能杜绝后期起皮开裂,却耽误师傅一整天工期。
|
||||
木工进场要求所有接缝做 V 型槽、转角做 T 字型,虽能降低墙面开裂概率,却给师傅平添大量工序。
|
||||
瓦工施工时要求卫生间先找坡度、做回形地漏,下水快又美观,但要耗费师傅半天时间重新找平。
|
||||
瓦工未完工就提前买好地漏、止逆阀,强制要求一并安装,直接断了后期安装师傅的额外收入。
|
||||
(备注:保留原文 6 个要点,按原文序号排列,保留原文核心细节和逻辑,适当调整句式让口语化更贴合口播,不篡改每层背后的利弊关系)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文 6 个要点的序号排列,不随机抽取、不打乱顺序,保证内容连贯性,贴合家装从水电、防水、木工到瓦工的施工流程,层层递进符合业主认知。
|
||||
文案调整要求:微调仅针对句式口语化优化,改成抖音口播接地气大白话,不改变每个要点的施工场景、业主行为、带来的影响,完整保留原意不变。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解饱满不拖沓,符合短视频完播习惯。
|
||||
内容适配性:6 个要点讲解衔接自然,每点独立成段适配空镜分镜,聚焦业主不懂行乱指挥、盲目加活的通病,既讲做法又讲背后利弊,真实接地气、容易引发共鸣。
|
||||
结尾范式:以 “如果你也准备新房装修,我整理了一份装修全流程避坑手册。评论区回复避坑,拿去用。” 为核心句式,保留原文结尾结构和领资料引导话术,仅可轻微优化口语流畅度,不改动核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇严格遵循核心强制规则原句,3 秒抓眼球不拖沓,用真实行业视角吐槽业主盲目干预施工的通病,贴合装修受众共情点,不偏离范式结构。
|
||||
全程口语化大白话,小白易懂、不生硬说教,站客观中立角度讲解,语气接地气有真实感,贴合口播传播特点。
|
||||
可微调句式语序,严禁篡改 6 个要点的施工场景、业主行为、利弊细节,每句带标点规范断句,适配口播节奏,避免大长句。
|
||||
【内置固定原文案】
|
||||
装修师傅最讨厌业主干的 6 件事,尤其是最后一点。
|
||||
第一,水电材料刚进场,就要求师傅所有的转角全部用大弧弯,你不提师傅全用直角弯,你洗澡时倒是水流更大了,又给装修师傅增加成本。
|
||||
第二,水电还没完工,你就提前买好了黄金蜂窝阻尼片和隔音棉,非要包卫生间和阳台的下水管道,说这样不会被楼上的出水噪音吵醒,但师傅又多了些活儿。
|
||||
第三,防水师傅刚准备动手刷防水涂料,业主就喊停,让师傅把开发商原有的防水全部铲掉,再把地面打扫干净。说这样防水才不会起皮开裂。你家卫生间倒是不漏水了,做这两样活儿又要耽误师傅一天工期。
|
||||
第四,木工师傅高高兴兴来了,你却告诉他,所有接缝处都要做 V 字型槽,转角处要做到 T 字型。师傅一听就知道你是懂行的。后期墙面是不容易开裂了,又给师傅增加好多活儿。
|
||||
第五,瓦工师傅来了,懂行的业主要求把卫生间先找坡度,地漏做成回形地漏,这样不仅下水快,还好看,可这又得浪费师傅半天时间,重新找坡度。
|
||||
第六,瓦工还没结束,部分业主已经提前买好了地漏和油烟止逆阀,要求师傅一并装上。这下好了,之后安装电器的师傅想赚点外快都不行。
|
||||
如果你也准备新房装修,我整理了一份装修全流程避坑手册。评论区回复避坑,拿去用。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修施工、业主干预工序主题,优先选贴砖恶搞、墙面空鼓、水电施工等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选水电施工、防水施工、木作基层、瓷砖铺贴等贴合家装全流程主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,瓦工结束后不能立马验收,至少要等五六天。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “装修师傅最讨厌业主 6 件事,千万别乱干预施工” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
@@ -1,260 +1,260 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备签装修合同、不懂条款陷阱、容易被低价全包套路、后期增项加价被牵制的装修业主,围绕装修签约必盯 3 大核心要点及备注条款创作,按原文逻辑顺序排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头签约痛点引入 + 合同 3 大避坑干货 + 结尾合同模板引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用扎心现实视角点出签合同前后地位反差、低价全包后期翻倍加价的痛点,引出下文 3 个必盯关键点。
|
||||
中间核心(装修合同 3 大避坑要点 + 备注条款,文案适当调整修改,意思保持原意,按原文逻辑顺序排列,不随机抽取):
|
||||
违约金条款:装修公司常设 20% 至 30% 高额违约条款,无施工反悔也要高额赔付,签约务必改成 3%,把自身风险降到最低。
|
||||
付款节点:拒绝 60%、80% 高首付套路,手握资金才有主动权;按 15% 开工、30% 水电验收、30% 木瓦工验收、20% 油工验收、5% 竣工尾款的标准付款最稳妥。
|
||||
合同备注栏:一定要逐条补充关键约定,涵盖环保建材检测、工地安全责任、结构隐患追责、工期延误赔付、赠送家电安装节点五大保障内容,全方位约束装修公司。
|
||||
(备注:保留原文 3 大要点及 5 条备注核心细节、数字比例、责任约定不变,适当调整句式让口语化更贴合口播,不篡改条款利弊、付款比例、赔付规则核心逻辑)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文违约金、付款方式、备注栏三大板块顺序排列,不打乱结构,贴合业主签合同逐条审核的真实流程,层层递进符合认知逻辑。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面合同话术改成抖音口播接地气大白话,不改变违约金比例、付款节点金额、备注 5 条硬性约定等所有核心数字和规则,完整保留原文原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解条款细致不啰嗦,节奏适中,适配短视频完播率。
|
||||
内容适配性:三大要点及备注条款衔接自然,每部分独立适配空镜分镜,直击业主签约被套路、后期加价维权难的核心痛点,每一条都讲清陷阱、整改方法和保障作用,实用性极强。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修合同模板、评论区扣关键词引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文扎心吐槽语气,3 秒抓眼球,点破装修签合同前后身份反差、低价全包套路深坑,瞬间引发准备装修业主共鸣。
|
||||
全程口语化大白话,通俗易懂、接地气,站业主立场拆解合同陷阱,条理清晰、干货满满,不生硬说教,适配口播传播节奏。
|
||||
可微调句式语序,严禁篡改违约金比例、付款节点数值、备注五条约定的核心内容和硬性规则,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
装修签合同前你是上帝,签完合同立刻变成弱势群体。装修签合同说好了 10 万全包,最后装完你要花 20 万,不给钱还要起诉你,抓住我下面说的 3 点,盯紧了,后期绝对少遭罪。
|
||||
第一个违约金,很多装修公司填百分之二十、三十,要是反悔了,什么也没干,就得赔两万,这就是把你绑死的条款。签合同必须改成 3%,最多亏 3000,把风险降到最低。
|
||||
第二个付款方式,别被百分之六十、百分之八十的首付款给坑了。钱一交就没有主动权,工地出问题只能被动整改。按我说的,签合同时付 15%,水电防水等隐蔽工程验收合格后付 30%,瓦工、木工验收合格了付 30%,油工验收合格了付 20%,竣工验收没问题,再付最后的 5%。钱在手里才有主动权。
|
||||
第三个备注栏,这是个保障,千万别忽略,照着填:
|
||||
1,乙方承诺使用环保建材,施工完成后,甲方可在自主材料未进场时进行空气检测,环保不达标,乙方全额返还所有施工费用。
|
||||
2,工地及工人的人身安全由乙方全权负责,甲方不承担任何责任。
|
||||
3,因设计和施工造成的房屋、墙体等结构安全隐患,由乙方全权负责。
|
||||
4,若乙方原因延误工期,每延误一天,支付工程款总费用的 1%。
|
||||
5,乙方承诺赠送的家电,必须在甲方支付最后一笔工程款之前安装到位。
|
||||
合同这么签,谁都坑不了你。记不住的,我整理了装修合同模板,抠合同拿去用,对着谈准没错。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修合同签约、条款避坑主题,优先选工地恶搞、装修合同核对、毛坯全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选装修合同核对、现场交底、全屋验收等贴合合同签约避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备签装修合同、不懂条款陷阱、容易被低价全包套路、后期增项加价被牵制的装修业主,围绕装修签约必盯 3 大核心要点及备注条款创作,按原文逻辑顺序排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头签约痛点引入 + 合同 3 大避坑干货 + 结尾合同模板引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用扎心现实视角点出签合同前后地位反差、低价全包后期翻倍加价的痛点,引出下文 3 个必盯关键点。
|
||||
中间核心(装修合同 3 大避坑要点 + 备注条款,文案适当调整修改,意思保持原意,按原文逻辑顺序排列,不随机抽取):
|
||||
违约金条款:装修公司常设 20% 至 30% 高额违约条款,无施工反悔也要高额赔付,签约务必改成 3%,把自身风险降到最低。
|
||||
付款节点:拒绝 60%、80% 高首付套路,手握资金才有主动权;按 15% 开工、30% 水电验收、30% 木瓦工验收、20% 油工验收、5% 竣工尾款的标准付款最稳妥。
|
||||
合同备注栏:一定要逐条补充关键约定,涵盖环保建材检测、工地安全责任、结构隐患追责、工期延误赔付、赠送家电安装节点五大保障内容,全方位约束装修公司。
|
||||
(备注:保留原文 3 大要点及 5 条备注核心细节、数字比例、责任约定不变,适当调整句式让口语化更贴合口播,不篡改条款利弊、付款比例、赔付规则核心逻辑)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文违约金、付款方式、备注栏三大板块顺序排列,不打乱结构,贴合业主签合同逐条审核的真实流程,层层递进符合认知逻辑。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面合同话术改成抖音口播接地气大白话,不改变违约金比例、付款节点金额、备注 5 条硬性约定等所有核心数字和规则,完整保留原文原意。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解条款细致不啰嗦,节奏适中,适配短视频完播率。
|
||||
内容适配性:三大要点及备注条款衔接自然,每部分独立适配空镜分镜,直击业主签约被套路、后期加价维权难的核心痛点,每一条都讲清陷阱、整改方法和保障作用,实用性极强。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修合同模板、评论区回复关键词引导的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文扎心吐槽语气,3 秒抓眼球,点破装修签合同前后身份反差、低价全包套路深坑,瞬间引发准备装修业主共鸣。
|
||||
全程口语化大白话,通俗易懂、接地气,站业主立场拆解合同陷阱,条理清晰、干货满满,不生硬说教,适配口播传播节奏。
|
||||
可微调句式语序,严禁篡改违约金比例、付款节点数值、备注五条约定的核心内容和硬性规则,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
装修签合同前你是上帝,签完合同立刻变成弱势群体。装修签合同说好了 10 万全包,最后装完你要花 20 万,不给钱还要起诉你,抓住我下面说的 3 点,盯紧了,后期绝对少遭罪。
|
||||
第一个违约金,很多装修公司填百分之二十、三十,要是反悔了,什么也没干,就得赔两万,这就是把你绑死的条款。签合同必须改成 3%,最多亏 3000,把风险降到最低。
|
||||
第二个付款方式,别被百分之六十、百分之八十的首付款给坑了。钱一交就没有主动权,工地出问题只能被动整改。按我说的,签合同时付 15%,水电防水等隐蔽工程验收合格后付 30%,瓦工、木工验收合格了付 30%,油工验收合格了付 20%,竣工验收没问题,再付最后的 5%。钱在手里才有主动权。
|
||||
第三个备注栏,这是个保障,千万别忽略,照着填:
|
||||
1,乙方承诺使用环保建材,施工完成后,甲方可在自主材料未进场时进行空气检测,环保不达标,乙方全额返还所有施工费用。
|
||||
2,工地及工人的人身安全由乙方全权负责,甲方不承担任何责任。
|
||||
3,因设计和施工造成的房屋、墙体等结构安全隐患,由乙方全权负责。
|
||||
4,若乙方原因延误工期,每延误一天,支付工程款总费用的 1%。
|
||||
5,乙方承诺赠送的家电,必须在甲方支付最后一笔工程款之前安装到位。
|
||||
合同这么签,谁都坑不了你。记不住的,我整理了装修合同模板,回复合同拿去用,对着谈准没错。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修合同签约、条款避坑主题,优先选工地恶搞、装修合同核对、毛坯全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选装修合同核对、现场交底、全屋验收等贴合合同签约避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
@@ -1,260 +1,260 @@
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将签订装修合同、担心合同条款有陷阱、怕被装修公司钻文字空子坑钱的业主,严格围绕装修合同避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机4点合同避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:签合同】,谁要是给你一上来就【错误操作:拿模糊条款合同】,你就直接【拒绝动作:别签他】。你以为他是帮你【表面好处:省麻烦、省时间】,其实他就是图【错误目的:钻文字空子、坑你钱】。下面这4点一定要看仔细,少看一条都可能亏几万!”为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6个装修合同避坑要点,文案适当调整修改,意思保持原意,随机抽取4个重编序号):
|
||||
1. 工期陷阱:平层硬装90个自然日足够,扣除周末不施工,实际干活六七十天。没约定工期可能拖一年半载。
|
||||
2. 延期赔偿:延期一天赔万分之二不合理,按6万半包算一天才12元,拖一个月才360元。延期赔偿必须按每天2‰写。
|
||||
3. 付款方式:必须验收后付,不是验收前。建议:签完合同时付15%,水电验收完付30%,泥木工验收完付30%,涂料验收完付20%,全部竣工验收完再付5%。
|
||||
4. 材料调换坑:条款写着材料断货可用同等价钱调换,这条是偷工减料的正当理由。等价杂牌不敢用,必须划掉这条。
|
||||
5. 安全责任:80%的公司只写按安全标准施工,但出事谁负责?合同必须注明工人人身安全及财产损失全部由装修公司承担。
|
||||
6. 违约金恶心点:单方面解约违约金写得很高,公司不会主动解约,就是为了绑死客户。违约金超过20%直接拉黑,别犹豫。
|
||||
(备注:随机抽取上述4点作为中间核心,重编序号,保留原文核心数据和避坑逻辑,适当调整句式让口语化更贴合口播)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑指南】,抠【核心关键词:合同】直接拿走,对照检查,少踩坑!”
|
||||
【开篇&语言要求】
|
||||
开篇1–2句话钩子,直击装修合同文字陷阱、被装修公司坑钱的痛点,3秒抓眼球,不拖沓不铺垫(保留原文“玩的都是文字游戏,少踩一个坑等于多赚一笔钱”核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文中工期、赔偿金比例、付款节点、材料条款等核心数字数据,每句必须带标点断句。
|
||||
【细节固定要求】
|
||||
结尾必须固定话术:我整理了装修全流程避坑指南,抠合同直接拿走。同时保留原文结尾“记不住的,我整理了装修合同样本,评论区抠合同,直接拿着对照检查,少踩坑!”
|
||||
总分镜数量固定12–20个,每个分镜时长3–8秒,可保留两位小数。
|
||||
【内置固定原文案】
|
||||
新房装修签合同千万注意这6个点,玩的都是文字游戏,耐心听我讲完,少踩一个坑等于多赚一笔钱。
|
||||
第一,工期。一般平层硬装90个自然日就足够了,扣除周末不能施工,真正干活六七十天完全可行。你要是没约定好,装修公司给你拖个一年半载,你哭都没地方。
|
||||
第二,延期赔偿金。延误工期后,很多公司写延期一天赔万分之二,按6万半包算,一天才12块钱,拖一个月才360块钱。你觉得有约束力吗?工期咱可以自己宽限,但延期赔偿一定要按每天2‰来写。
|
||||
第三,付款方式。一定要按我说的,记住付款节点一定要写清楚,是验收后付,不是验收前。比如,签完合同时付15%,水电验收完付30%,泥木工验收完付30%,涂料验收完付20%,全部竣工验收完再付5%。
|
||||
第四,材料调换坑。很多公司条款上面写着,当材料断货时,可用同等价钱调换,但有这条,偷工减料就成了理所当然。同价产品很难界定,同价的杂牌你敢用吗?这条必须划掉。
|
||||
第五,安全责任。有80%的公司只写按安全标准施工,但别不提出事谁负责?一旦发生安全事故,就是扯不完的皮。合同里必须注明工人人身安全及财产损失全部由装修公司承担。
|
||||
第六,也是最恶心的一点,很多公司把单方面解约违约金写得很高,他们根本不会主动解约,这条就是为了绑死你。违约金超过20%,你发现问题也不敢换人,所以超过20%直接拉黑,别犹豫。
|
||||
记不住的,我整理了装修合同样本,评论区抠合同,直接拿走对照检查,少踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近合同主题,优先选装修合同核对、工地恶搞相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选合同签署、装修合同核对等贴合合同主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,装修报价别只看总价,漏一项,后期就得多花好几万。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离440–480(含数字,不含标点符号)、总时长偏离110–120秒。
|
||||
禁止篡改原文合同避坑相关的工期、赔偿金比例、付款节点等核心数据。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “工地恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “新房装修签合同,全是文字游戏,少踩坑等于多赚钱”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “拿模糊条款合同给你的装修公司,直接别签别客气”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “装修合同核对 - 现场交底”,
|
||||
“voiceover”: “他不是省麻烦,是想钻空子坑你钱,这4点必看”,
|
||||
“duration”: “4.75s”
|
||||
}
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将签订装修合同、担心合同条款有陷阱、怕被装修公司钻文字空子坑钱的业主,严格围绕装修合同避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机4点合同避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:签合同】,谁要是给你一上来就【错误操作:拿模糊条款合同】,你就直接【拒绝动作:别签他】。你以为他是帮你【表面好处:省麻烦、省时间】,其实他就是图【错误目的:钻文字空子、坑你钱】。下面这4点一定要看仔细,少看一条都可能亏几万!”为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(6个装修合同避坑要点,文案适当调整修改,意思保持原意,随机抽取4个重编序号):
|
||||
1. 工期陷阱:平层硬装90个自然日足够,扣除周末不施工,实际干活六七十天。没约定工期可能拖一年半载。
|
||||
2. 延期赔偿:延期一天赔万分之二不合理,按6万半包算一天才12元,拖一个月才360元。延期赔偿必须按每天2‰写。
|
||||
3. 付款方式:必须验收后付,不是验收前。建议:签完合同时付15%,水电验收完付30%,泥木工验收完付30%,涂料验收完付20%,全部竣工验收完再付5%。
|
||||
4. 材料调换坑:条款写着材料断货可用同等价钱调换,这条是偷工减料的正当理由。等价杂牌不敢用,必须划掉这条。
|
||||
5. 安全责任:80%的公司只写按安全标准施工,但出事谁负责?合同必须注明工人人身安全及财产损失全部由装修公司承担。
|
||||
6. 违约金恶心点:单方面解约违约金写得很高,公司不会主动解约,就是为了绑死客户。违约金超过20%直接拉黑,别犹豫。
|
||||
(备注:随机抽取上述4点作为中间核心,重编序号,保留原文核心数据和避坑逻辑,适当调整句式让口语化更贴合口播)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑指南】,回复【核心关键词:合同】直接拿走,对照检查,少踩坑!”
|
||||
【开篇&语言要求】
|
||||
开篇1–2句话钩子,直击装修合同文字陷阱、被装修公司坑钱的痛点,3秒抓眼球,不拖沓不铺垫(保留原文“玩的都是文字游戏,少踩一个坑等于多赚一笔钱”核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文中工期、赔偿金比例、付款节点、材料条款等核心数字数据,每句必须带标点断句。
|
||||
【细节固定要求】
|
||||
结尾必须固定话术:我整理了装修全流程避坑指南,回复合同直接拿走。同时保留原文结尾“记不住的,我整理了装修合同样本,评论区回复合同,直接拿着对照检查,少踩坑!”
|
||||
总分镜数量固定12–20个,每个分镜时长3–8秒,可保留两位小数。
|
||||
【内置固定原文案】
|
||||
新房装修签合同千万注意这6个点,玩的都是文字游戏,耐心听我讲完,少踩一个坑等于多赚一笔钱。
|
||||
第一,工期。一般平层硬装90个自然日就足够了,扣除周末不能施工,真正干活六七十天完全可行。你要是没约定好,装修公司给你拖个一年半载,你哭都没地方。
|
||||
第二,延期赔偿金。延误工期后,很多公司写延期一天赔万分之二,按6万半包算,一天才12块钱,拖一个月才360块钱。你觉得有约束力吗?工期咱可以自己宽限,但延期赔偿一定要按每天2‰来写。
|
||||
第三,付款方式。一定要按我说的,记住付款节点一定要写清楚,是验收后付,不是验收前。比如,签完合同时付15%,水电验收完付30%,泥木工验收完付30%,涂料验收完付20%,全部竣工验收完再付5%。
|
||||
第四,材料调换坑。很多公司条款上面写着,当材料断货时,可用同等价钱调换,但有这条,偷工减料就成了理所当然。同价产品很难界定,同价的杂牌你敢用吗?这条必须划掉。
|
||||
第五,安全责任。有80%的公司只写按安全标准施工,但别不提出事谁负责?一旦发生安全事故,就是扯不完的皮。合同里必须注明工人人身安全及财产损失全部由装修公司承担。
|
||||
第六,也是最恶心的一点,很多公司把单方面解约违约金写得很高,他们根本不会主动解约,这条就是为了绑死你。违约金超过20%,你发现问题也不敢换人,所以超过20%直接拉黑,别犹豫。
|
||||
记不住的,我整理了装修合同样本,评论区回复合同,直接拿走对照检查,少踩坑!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近合同主题,优先选装修合同核对、工地恶搞相关)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选合同签署、装修合同核对等贴合合同主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
“分镜文案"等于"配音文案”,“配音文案”必须要有标点符号断句,避免大长句,如:“第一,装修报价别只看总价,漏一项,后期就得多花好几万。”每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的"分镜时长"为{严格按**每秒4个纯文字**计算时长。文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算,即"分镜文案"的纯文字字数/4},严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s"
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离440–480(含数字,不含标点符号)、总时长偏离110–120秒。
|
||||
禁止篡改原文合同避坑相关的工期、赔偿金比例、付款节点等核心数据。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “工地恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “新房装修签合同,全是文字游戏,少踩坑等于多赚钱”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “拿模糊条款合同给你的装修公司,直接别签别客气”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “装修合同核对 - 现场交底”,
|
||||
“voiceover”: “他不是省麻烦,是想钻空子坑你钱,这4点必看”,
|
||||
“duration”: “4.75s”
|
||||
}
|
||||
]
|
||||
@@ -1,262 +1,262 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、即将签署装修合同,担心直接签装修公司固定模板踩坑、后期扯皮加价、权益无保障的业主,严格围绕装修合同 8 条必签避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 8 条装修合同避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:签装修合同】,谁要是直接照搬【错误操作:装修公司固定模板】就签字,你就直接【拒绝动作:别盲目乱签】。你以为他是帮你【表面好处:省事、不用自己琢磨】,其实他就是图【错误目的:埋下陷阱、后期挖坑加价】。下面这 8 条一定要白纸黑字写进合同,少一条都保不住自身权益!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(8 条装修合同避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
工期保修:合同写清施工工期和售后保修期,杜绝工期拖延、工程烂尾,后期维修费用由装修公司全权承担,避免出问题不认账。
|
||||
安全责任:明确划分施工安全责任,砸拆承重墙、工人施工意外等所有责任,全部由装修公司承担,避免业主无辜承担损失、被工人碰瓷。
|
||||
总价税金:锁定合同固定总价,标注是否含税,竣工结算严禁随意调价,项目变更价款控制在 5% 以内,杜绝恶意增项乱加钱。
|
||||
付款比例:约定按施工节点比例付款,每环节验收合格再支付款项,不提前大额预交,建议签合同仅付 15%,大幅降低装修风险。
|
||||
工程验收:按行业新标准执行分段验收,每道工序完工必须通知业主到场,验收合格方可进入下一步,禁止跳过验收埋下质量隐患。
|
||||
材料约定:写明材料品牌型号规格,落实假一罚十条款,所有材料需业主确认无误后再施工,防止装修公司以次充好、偷换主材。
|
||||
甲醛整改:约定全屋甲醛检测若不合格,由装修公司负责免费整改,并承担全部相关费用,避免入住甲醛超标、维权无门。
|
||||
违约赔付:明确双方违约责任,写清违约金比例和逾期赔付金额,约束双方行为,让装修公司不敢随意违约、敷衍施工。
|
||||
(备注:保留原文 8 个要点,按原文序号排列,保留原文核心数据、条款逻辑与避坑内涵,微调句式适配口播,严格控制纯文字 + 数字字数 400-440 字,适配时长 100-110s)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修标准合同模板】,抠【核心关键词:装修】直接拿走,对照检查,少踩坑!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击装修签合同盲目乱签、被模板套路、后期权益受损的痛点,3 秒抓眼球,不拖沓不铺垫(保留原文 “准备装修的家人们注意了!签合同别瞎签,装修公司固定模板直接签必踩坑” 核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文合同工期、付款比例、变更价款 5%、15% 预付款等核心数字与权责逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
准备装修的家人们注意了!签合同别瞎签,装修公司的固定模板,直接签必踩坑!下面这 8 条,必须白纸黑字写清楚,才能保住你的权益!
|
||||
第一,写清工期和保修期,防止脱工烂尾,保修费全由装修公司承担。不然装修公司拖工期、后期出问题不认账,你没处说理。
|
||||
第二,安全责任分清楚,砸承重墙、工人出事,全由装修公司负责。别被工人碰瓷,最后自己承担不必要的损失。
|
||||
第三,固定合同总价,含不含税金写明白,结算不随意调价,变更价款不超 5%。避免装修公司乱加钱,保障自身权益。
|
||||
第四,按比例付款,验收合格再给钱,别一上来交太多。签合同付 15%,验收合格再付剩余部分,降低风险。
|
||||
第五,工程验收按新标准,每个环节必须通知你,验收合格再下一步。不让装修公司跳过验收,埋下质量隐患。
|
||||
第六,材料假一罚十,品牌型号对好,你确认后再施工。防止装修公司以次充好,偷换材料。
|
||||
第七,甲醛检测不合格,装修公司整改并承担所有费用。避免入住后甲醛超标,维权无门。
|
||||
第八,违约责任划清楚,违约金和逾期赔付金额写明白。保障自己权益,让装修公司不敢随意违约。
|
||||
准备装修的,我整理了合同模板,评论区扣装修就能领!帮你装修少踩坑、省麻烦!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修合同主题,优先选工地恶搞、装修合同核对、合同签署等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选合同签署、装修合同核对、施工方案现场讲解等贴合合同签约主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,装修报价别只看总价,漏一项,后期就得多花好几万。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 400–440(含数字,不含标点符号)、总时长偏离 100–110 秒。
|
||||
禁止篡改原文装修合同避坑相关的工期、付款比例、变更价款、权责划分等核心数据和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “工地恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “新房装修签合同,全是文字游戏,少踩坑等于多赚钱”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “拿固定模板合同给你的装修公司,千万别直接签”,
|
||||
“duration”: “5s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “装修合同核对 - 现场交底”,
|
||||
“voiceover”: “8 条条款必须写进合同,条条守住你的装修权益”,
|
||||
“duration”: “5s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备新房装修、即将签署装修合同,担心直接签装修公司固定模板踩坑、后期扯皮加价、权益无保障的业主,严格围绕装修合同 8 条必签避坑要点创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 8 条装修合同避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:以 “新房装修【核心场景:签装修合同】,谁要是直接照搬【错误操作:装修公司固定模板】就签字,你就直接【拒绝动作:别盲目乱签】。你以为他是帮你【表面好处:省事、不用自己琢磨】,其实他就是图【错误目的:埋下陷阱、后期挖坑加价】。下面这 8 条一定要白纸黑字写进合同,少一条都保不住自身权益!” 为核心句式,用警示性语气点出常见坑,引出下文要点(保留原文开头核心原意,适配范式结构)。
|
||||
中间核心(8 条装修合同避坑要点,文案适当调整修改,意思保持原意,按原文序号排列,不随机抽取):
|
||||
工期保修:合同写清施工工期和售后保修期,杜绝工期拖延、工程烂尾,后期维修费用由装修公司全权承担,避免出问题不认账。
|
||||
安全责任:明确划分施工安全责任,砸拆承重墙、工人施工意外等所有责任,全部由装修公司承担,避免业主无辜承担损失、被工人碰瓷。
|
||||
总价税金:锁定合同固定总价,标注是否含税,竣工结算严禁随意调价,项目变更价款控制在 5% 以内,杜绝恶意增项乱加钱。
|
||||
付款比例:约定按施工节点比例付款,每环节验收合格再支付款项,不提前大额预交,建议签合同仅付 15%,大幅降低装修风险。
|
||||
工程验收:按行业新标准执行分段验收,每道工序完工必须通知业主到场,验收合格方可进入下一步,禁止跳过验收埋下质量隐患。
|
||||
材料约定:写明材料品牌型号规格,落实假一罚十条款,所有材料需业主确认无误后再施工,防止装修公司以次充好、偷换主材。
|
||||
甲醛整改:约定全屋甲醛检测若不合格,由装修公司负责免费整改,并承担全部相关费用,避免入住甲醛超标、维权无门。
|
||||
违约赔付:明确双方违约责任,写清违约金比例和逾期赔付金额,约束双方行为,让装修公司不敢随意违约、敷衍施工。
|
||||
(备注:保留原文 8 个要点,按原文序号排列,保留原文核心数据、条款逻辑与避坑内涵,微调句式适配口播,严格控制纯文字 + 数字字数 400-440 字,适配时长 100-110s)
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修标准合同模板】,回复【核心关键词:装修】直接拿走,对照检查,少踩坑!”
|
||||
【开篇 & 语言要求】
|
||||
开篇钩子,直击装修签合同盲目乱签、被模板套路、后期权益受损的痛点,3 秒抓眼球,不拖沓不铺垫(保留原文 “准备装修的家人们注意了!签合同别瞎签,装修公司固定模板直接签必踩坑” 核心钩子)。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改原文合同工期、付款比例、变更价款 5%、15% 预付款等核心数字与权责逻辑,每句必须带标点断句。
|
||||
【内置固定原文案】
|
||||
准备装修的家人们注意了!签合同别瞎签,装修公司的固定模板,直接签必踩坑!下面这 8 条,必须白纸黑字写清楚,才能保住你的权益!
|
||||
第一,写清工期和保修期,防止脱工烂尾,保修费全由装修公司承担。不然装修公司拖工期、后期出问题不认账,你没处说理。
|
||||
第二,安全责任分清楚,砸承重墙、工人出事,全由装修公司负责。别被工人碰瓷,最后自己承担不必要的损失。
|
||||
第三,固定合同总价,含不含税金写明白,结算不随意调价,变更价款不超 5%。避免装修公司乱加钱,保障自身权益。
|
||||
第四,按比例付款,验收合格再给钱,别一上来交太多。签合同付 15%,验收合格再付剩余部分,降低风险。
|
||||
第五,工程验收按新标准,每个环节必须通知你,验收合格再下一步。不让装修公司跳过验收,埋下质量隐患。
|
||||
第六,材料假一罚十,品牌型号对好,你确认后再施工。防止装修公司以次充好,偷换材料。
|
||||
第七,甲醛检测不合格,装修公司整改并承担所有费用。避免入住后甲醛超标,维权无门。
|
||||
第八,违约责任划清楚,违约金和逾期赔付金额写明白。保障自己权益,让装修公司不敢随意违约。
|
||||
准备装修的,我整理了合同模板,评论区回复装修就能领!帮你装修少踩坑、省麻烦!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近装修合同主题,优先选工地恶搞、装修合同核对、合同签署等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选合同签署、装修合同核对、施工方案现场讲解等贴合合同签约主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,如:“第一,装修报价别只看总价,漏一项,后期就得多花好几万。” 每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s"
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
禁止总字数偏离 400–440(含数字,不含标点符号)、总时长偏离 100–110 秒。
|
||||
禁止篡改原文装修合同避坑相关的工期、付款比例、变更价款、权责划分等核心数据和逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “工地恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “新房装修签合同,全是文字游戏,少踩坑等于多赚钱”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “拿固定模板合同给你的装修公司,千万别直接签”,
|
||||
“duration”: “5s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “装修合同核对 - 现场交底”,
|
||||
“voiceover”: “8 条条款必须写进合同,条条守住你的装修权益”,
|
||||
“duration”: “5s”
|
||||
}
|
||||
]
|
||||
@@ -1,296 +1,296 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备找装修公司、不懂怎么咨询避坑、容易被低价套路、前期没问清后期疯狂增项多花冤枉钱的业主,围绕装修 18 个必问核心问题做避坑口播内容,帮业主提前问清关键要点,规避装修陷阱。
|
||||
(二)脚本类型
|
||||
装修咨询避坑口播短视频脚本,结构固定:保留原版完整开头 + 18 个问题随机打乱重新编排顺序、适度口语微调 + 保留原版完整结尾引导,无多余内容,不增减问题数量,不篡改核心逻辑。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄,适配抖音、视频号口播节奏,适合中长干货类短视频,兼顾完播率和实用性。
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
完整保留原文开头一字不变:装修不懂问这几个问题,至少让你亏几万。沿用警示性痛点语气,直击业主不懂咨询、容易被装修公司套路亏钱的核心痛点,简洁有力,3 秒抓眼球,引出下文 18 个必问问题,不改写、不替换、不重新创作开头,不添加任何多余话术。
|
||||
中间核心
|
||||
1、 严格保留全部18 个问题原文核心原意,不删减、不新增、不篡改任何问题内涵、关键询问点和核心诉求;
|
||||
2、 每次生成都自动随机打乱 18 个问题的排列顺序,重新自主编排,不固定顺序,每次生成均为不同排列组合;
|
||||
3、 可适当做口语化顺滑微调、精简冗余语气词,适配口播语感,让语句更自然接地气,但不能改变问题本意、关键信息和询问方向;
|
||||
4、 纯文字 + 数字扣除标点严格锁定 440-480 字,对应时长110-120s,按每秒 4 个字核算,不偏离字数和时长区间,确保内容饱满不拖沓。
|
||||
18 个装修必问原始问题汇总
|
||||
1、前期承诺我免费设计和量房,后期不会又问我要两三千设计费吧?
|
||||
2、目前在施工的有几家,能领我上现场看看不?
|
||||
3、装修全程是不是只用一个人对接?
|
||||
4、交完定金我不想找你装修了,是全款退还是扣我违约金?
|
||||
5、工地是自己的工人还是外包的?
|
||||
6、合同签完啥时候能开工?
|
||||
7、全程节点验收是多少次?要不要我每次都到现场签字?
|
||||
8、要是我没空跑工地,怎么了解工地的进度?
|
||||
9、能不能给我你家的标准施工流程和验收规范?
|
||||
10、水电是怎么走线和收费的?
|
||||
11、材料都是什么品牌?环保等级能达到什么标准?
|
||||
12、拆墙垃圾包不包清运下楼?垃圾清运费咋算的?
|
||||
13、卫生间防水标准是多少?厨房做防水要不要单独加钱?
|
||||
14、过门石、踢脚线这些玩意儿是不是另算钱?
|
||||
15、展厅主材随便选吗?套餐内有什么限制?
|
||||
16、橱柜限不限米数和形状,增项的地方在哪里?
|
||||
17、装修工期多长时间能装完?如果延期了怎么赔?
|
||||
18、售后保几年?水电、防水、基础施工、主材都得说清楚。
|
||||
结尾范式
|
||||
完整保留原文结尾原话一字不变:想知道这些问题的标准答案,我都整理在装修避坑手册里了,回个避坑直接拿去。不改动引流逻辑、不改写语句、不新增多余话术,保持原有引流引导的简洁性和实用性。
|
||||
【开篇 & 语言要求】
|
||||
开篇完全沿用原版固定文案,不做任何修改,直击装修咨询踩坑、亏钱痛点,3 秒抓住装修业主注意力,不拖沓、不铺垫;
|
||||
全程采用接地气大白话、内行唠嗑口吻,贴合普通业主咨询装修的真实语境,不生硬说教、不堆砌专业术语,让小白业主一听就懂;
|
||||
仅可微调 18 个问题的语序、顺滑口语表达,删减冗余语气词(不改变原意),严禁篡改 18 个问题的核心询问点、关键诉求和关键信息;
|
||||
每句必须带标点规范断句,适配口播节奏,避免超长句子,确保语速平缓、干货清晰,贴合中长干货类短视频的完播习惯。
|
||||
【内置固定原文案】
|
||||
装修不懂问这几个问题,至少让你亏几万
|
||||
第一问,前期承诺我免费设计和量房,后期不会又问我要两三千设计费吧?
|
||||
第二问,目前在施工的有几家,能领我上现场看看不?
|
||||
第三问,装修全程是不是只用一个人对接?
|
||||
第四问,交完定金我不想找你装修了,是全款退还是扣我违约金?
|
||||
第五问,工地是自己的工人还是外包的?
|
||||
第六问,合同签完啥时候能开工?
|
||||
第七问,全程节点验收是多少次?要不要我每次都到现场签字?
|
||||
第八问,要是我没空跑工地,怎么了解工地的进度?
|
||||
第九问,能不能给我你家的标准施工流程和验收规范?
|
||||
第十问,水电是怎么走线和收费的?
|
||||
第十一问,材料都是什么品牌?环保等级能达到什么标准?
|
||||
第十二问,拆墙垃圾包不包清运下楼?垃圾清运费咋算的?
|
||||
第十三问,卫生间防水标准是多少?厨房做防水要不要单独加钱?
|
||||
第十四问,过门石、踢脚线这些玩意儿是不是另算钱?
|
||||
第十五问,展厅主材随便选吗?套餐内有什么限制?
|
||||
第十六问,橱柜限不限米数和形状,增项的地方在哪里?
|
||||
第十七问,装修工期多长时间能装完?如果延期了怎么赔?
|
||||
第十八问,售后保几年?水电、防水、基础施工、主材都得说清楚。
|
||||
想知道这些问题的标准答案,我都整理在装修避坑手册里了,回个避坑直接拿去
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴近装修咨询、装修套路、施工避坑主题,优先选工地恶搞、装修合同核对、施工翻车镜等相关素材)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜,确保开篇画面有吸睛点、有人物共情、有场景铺垫。
|
||||
分点阐述(18 个问题)全部用空镜,空镜素材库标题与文案内容需精准匹配(如咨询合同相关问题,匹配 “装修合同核对”;咨询水电相关问题,匹配 “水电验收”“水路施工” 等),匹配不到则优先选现场交底、量房勘测、主材安装等装修相关近似空镜,确保画面与配音高度契合。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜,空镜优先选装修避坑相关、成品验收相关素材,呼应结尾引流引导。
|
||||
分镜文案 = 配音文案,必须要有标点符号断句,避免大长句;每段分镜文案纯文字含数字、不含标点严格控制 12-32 个字,超长句必须拆分多分镜,语句通顺完整,不拆分原意。
|
||||
全篇文案硬性约束:纯文字 + 数字扣除标点严控440-480 字、总时长锁定110-120s,不得偏离区间,按每秒 4 个字精准核算总时长。
|
||||
每个分镜时长计算:严格按每秒 4 个纯文字核算,纯文字只统计汉字 + 阿拉伯数字、剔除标点符号;时长保留两位小数,单镜时长强制锁定 3-8 秒,超标必须拆句重分镜,不允许单镜时长超出或不足区间。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方内置素材库选匹配标题,不得随意更改 type 定义。
|
||||
人物出镜画面允许语句语意顺延到下一分镜,确保口播连贯性;空镜必须贴合当前配音文案的装修咨询主题,不选用与文案无关的素材。
|
||||
每次创作自动从 18 个问题中随机打乱全部顺序,重新编排,不固定组合、不固定顺序,确保每次生成的分镜文案顺序不同。
|
||||
禁止篡改原文 18 个问题的核心询问点、关键信息和原意,禁止增减问题数量,禁止偏离字数和时长要求。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块、注释、多余说明文字,不添加任何额外内容,严格遵循以下字段和格式要求:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…),不得重复、不得跳跃,严格按自然顺序编号
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充),严格对应定义,不得写错
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主;空镜必须从内置素材库中选择,不得自行创作场景)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合装修业主咨询避坑痛点,保留原文问题原意)
|
||||
duration: “分镜时长”(格式如 “5s”“5.25s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数,核算精准,不出现偏差)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "工地恶搞 - 恶搞开篇",
|
||||
"voiceover": "装修不懂问这几个问题,至少让你亏几万。",
|
||||
"duration": "4.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "找装修公司前,这 18 个问题一定要问清楚,别被坑!",
|
||||
"duration": "5.00s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "装修合同核对 - 现场交底",
|
||||
"voiceover": "第一问,交完定金不想装了,全款退还是扣违约金?",
|
||||
"duration": "5.50s"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "empty_shot",
|
||||
"scene": "设计师入户 - 量房勘测",
|
||||
"voiceover": "第二问,前期免费设计量房,后期会收设计费吗?",
|
||||
"duration": "5.25s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备找装修公司、不懂怎么咨询避坑、容易被低价套路、前期没问清后期疯狂增项多花冤枉钱的业主,围绕装修 18 个必问核心问题做避坑口播内容,帮业主提前问清关键要点,规避装修陷阱。
|
||||
(二)脚本类型
|
||||
装修咨询避坑口播短视频脚本,结构固定:保留原版完整开头 + 18 个问题随机打乱重新编排顺序、适度口语微调 + 保留原版完整结尾引导,无多余内容,不增减问题数量,不篡改核心逻辑。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄,适配抖音、视频号口播节奏,适合中长干货类短视频,兼顾完播率和实用性。
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
完整保留原文开头一字不变:装修不懂问这几个问题,至少让你亏几万。沿用警示性痛点语气,直击业主不懂咨询、容易被装修公司套路亏钱的核心痛点,简洁有力,3 秒抓眼球,引出下文 18 个必问问题,不改写、不替换、不重新创作开头,不添加任何多余话术。
|
||||
中间核心
|
||||
1、 严格保留全部18 个问题原文核心原意,不删减、不新增、不篡改任何问题内涵、关键询问点和核心诉求;
|
||||
2、 每次生成都自动随机打乱 18 个问题的排列顺序,重新自主编排,不固定顺序,每次生成均为不同排列组合;
|
||||
3、 可适当做口语化顺滑微调、精简冗余语气词,适配口播语感,让语句更自然接地气,但不能改变问题本意、关键信息和询问方向;
|
||||
4、 纯文字 + 数字扣除标点严格锁定 440-480 字,对应时长110-120s,按每秒 4 个字核算,不偏离字数和时长区间,确保内容饱满不拖沓。
|
||||
18 个装修必问原始问题汇总
|
||||
1、前期承诺我免费设计和量房,后期不会又问我要两三千设计费吧?
|
||||
2、目前在施工的有几家,能领我上现场看看不?
|
||||
3、装修全程是不是只用一个人对接?
|
||||
4、交完定金我不想找你装修了,是全款退还是扣我违约金?
|
||||
5、工地是自己的工人还是外包的?
|
||||
6、合同签完啥时候能开工?
|
||||
7、全程节点验收是多少次?要不要我每次都到现场签字?
|
||||
8、要是我没空跑工地,怎么了解工地的进度?
|
||||
9、能不能给我你家的标准施工流程和验收规范?
|
||||
10、水电是怎么走线和收费的?
|
||||
11、材料都是什么品牌?环保等级能达到什么标准?
|
||||
12、拆墙垃圾包不包清运下楼?垃圾清运费咋算的?
|
||||
13、卫生间防水标准是多少?厨房做防水要不要单独加钱?
|
||||
14、过门石、踢脚线这些玩意儿是不是另算钱?
|
||||
15、展厅主材随便选吗?套餐内有什么限制?
|
||||
16、橱柜限不限米数和形状,增项的地方在哪里?
|
||||
17、装修工期多长时间能装完?如果延期了怎么赔?
|
||||
18、售后保几年?水电、防水、基础施工、主材都得说清楚。
|
||||
结尾范式
|
||||
完整保留原文结尾原话一字不变:想知道这些问题的标准答案,我都整理在装修避坑手册里了,回个避坑直接拿去。不改动引流逻辑、不改写语句、不新增多余话术,保持原有引流引导的简洁性和实用性。
|
||||
【开篇 & 语言要求】
|
||||
开篇完全沿用原版固定文案,不做任何修改,直击装修咨询踩坑、亏钱痛点,3 秒抓住装修业主注意力,不拖沓、不铺垫;
|
||||
全程采用接地气大白话、内行唠嗑口吻,贴合普通业主咨询装修的真实语境,不生硬说教、不堆砌专业术语,让小白业主一听就懂;
|
||||
仅可微调 18 个问题的语序、顺滑口语表达,删减冗余语气词(不改变原意),严禁篡改 18 个问题的核心询问点、关键诉求和关键信息;
|
||||
每句必须带标点规范断句,适配口播节奏,避免超长句子,确保语速平缓、干货清晰,贴合中长干货类短视频的完播习惯。
|
||||
【内置固定原文案】
|
||||
装修不懂问这几个问题,至少让你亏几万
|
||||
第一问,前期承诺我免费设计和量房,后期不会又问我要两三千设计费吧?
|
||||
第二问,目前在施工的有几家,能领我上现场看看不?
|
||||
第三问,装修全程是不是只用一个人对接?
|
||||
第四问,交完定金我不想找你装修了,是全款退还是扣我违约金?
|
||||
第五问,工地是自己的工人还是外包的?
|
||||
第六问,合同签完啥时候能开工?
|
||||
第七问,全程节点验收是多少次?要不要我每次都到现场签字?
|
||||
第八问,要是我没空跑工地,怎么了解工地的进度?
|
||||
第九问,能不能给我你家的标准施工流程和验收规范?
|
||||
第十问,水电是怎么走线和收费的?
|
||||
第十一问,材料都是什么品牌?环保等级能达到什么标准?
|
||||
第十二问,拆墙垃圾包不包清运下楼?垃圾清运费咋算的?
|
||||
第十三问,卫生间防水标准是多少?厨房做防水要不要单独加钱?
|
||||
第十四问,过门石、踢脚线这些玩意儿是不是另算钱?
|
||||
第十五问,展厅主材随便选吗?套餐内有什么限制?
|
||||
第十六问,橱柜限不限米数和形状,增项的地方在哪里?
|
||||
第十七问,装修工期多长时间能装完?如果延期了怎么赔?
|
||||
第十八问,售后保几年?水电、防水、基础施工、主材都得说清楚。
|
||||
想知道这些问题的标准答案,我都整理在装修避坑手册里了,回个避坑直接拿去
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴近装修咨询、装修套路、施工避坑主题,优先选工地恶搞、装修合同核对、施工翻车镜等相关素材)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜,确保开篇画面有吸睛点、有人物共情、有场景铺垫。
|
||||
分点阐述(18 个问题)全部用空镜,空镜素材库标题与文案内容需精准匹配(如咨询合同相关问题,匹配 “装修合同核对”;咨询水电相关问题,匹配 “水电验收”“水路施工” 等),匹配不到则优先选现场交底、量房勘测、主材安装等装修相关近似空镜,确保画面与配音高度契合。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜,空镜优先选装修避坑相关、成品验收相关素材,呼应结尾引流引导。
|
||||
分镜文案 = 配音文案,必须要有标点符号断句,避免大长句;每段分镜文案纯文字含数字、不含标点严格控制 12-32 个字,超长句必须拆分多分镜,语句通顺完整,不拆分原意。
|
||||
全篇文案硬性约束:纯文字 + 数字扣除标点严控440-480 字、总时长锁定110-120s,不得偏离区间,按每秒 4 个字精准核算总时长。
|
||||
每个分镜时长计算:严格按每秒 4 个纯文字核算,纯文字只统计汉字 + 阿拉伯数字、剔除标点符号;时长保留两位小数,单镜时长强制锁定 3-8 秒,超标必须拆句重分镜,不允许单镜时长超出或不足区间。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方内置素材库选匹配标题,不得随意更改 type 定义。
|
||||
人物出镜画面允许语句语意顺延到下一分镜,确保口播连贯性;空镜必须贴合当前配音文案的装修咨询主题,不选用与文案无关的素材。
|
||||
每次创作自动从 18 个问题中随机打乱全部顺序,重新编排,不固定组合、不固定顺序,确保每次生成的分镜文案顺序不同。
|
||||
禁止篡改原文 18 个问题的核心询问点、关键信息和原意,禁止增减问题数量,禁止偏离字数和时长要求。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块、注释、多余说明文字,不添加任何额外内容,严格遵循以下字段和格式要求:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…),不得重复、不得跳跃,严格按自然顺序编号
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充),严格对应定义,不得写错
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主;空镜必须从内置素材库中选择,不得自行创作场景)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合装修业主咨询避坑痛点,保留原文问题原意)
|
||||
duration: “分镜时长”(格式如 “5s”“5.25s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数,核算精准,不出现偏差)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "工地恶搞 - 恶搞开篇",
|
||||
"voiceover": "装修不懂问这几个问题,至少让你亏几万。",
|
||||
"duration": "4.25s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "找装修公司前,这 18 个问题一定要问清楚,别被坑!",
|
||||
"duration": "5.00s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "装修合同核对 - 现场交底",
|
||||
"voiceover": "第一问,交完定金不想装了,全款退还是扣违约金?",
|
||||
"duration": "5.50s"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "empty_shot",
|
||||
"scene": "设计师入户 - 量房勘测",
|
||||
"voiceover": "第二问,前期免费设计量房,后期会收设计费吗?",
|
||||
"duration": "5.25s"
|
||||
}
|
||||
]
|
||||
@@ -1,265 +1,265 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:选择半包装修、不懂怎么询价、容易被装修公司套路报价、不知道该重点问哪些问题的装修业主,围绕半包装修必问 10 大关键问题创作,按原文逻辑顺序排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头询价痛点引入 + 半包 10 大必问问题干货 + 结尾资料领取引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用扎心视角点出半包业主盲目询价容易被当成新手收割、多花冤枉钱的痛点,引出下文必问 10 个关键问题。
|
||||
中间核心(半包装修 10 大必问问题要点,文案适当调整修改,意思保持原意,按原文序号逻辑排列,不随机抽取):
|
||||
拆改环节要问清:墙体拆除是否做切割施工,包含垃圾清运与否,旧门窗拆除能抵扣多少费用。
|
||||
水电环节逐项确认:水电是全改还是局部改造,电线水管品牌规格、壁厚、走顶走地工艺都要问清,布线方式与开关插座点位安装也要明确。
|
||||
瓷砖施工提前敲定:是否出具排版图纸,瓦工现场复尺落地,海棠角施工、全屋通铺是否额外收费。
|
||||
吊顶工艺核对细节:龙骨选用木龙骨还是轻钢龙骨,石膏板品牌、单层双层工艺,七字拐八字缝防裂工序是否标配。
|
||||
砌墙墙面基层问明白:墙固品牌与涂刷节点,挂网局部还是全屋、全屋挂网是否加价。
|
||||
辅材品牌提前锁定:腻子只选国产一线品牌,墙顶面只做顺平,柜子及边角局部找平即可。
|
||||
乳胶漆明确标准:确认乳胶漆品牌、是否涂刷底漆、整体涂刷遍数,全部写进合同备注。
|
||||
材料品质约束条款:约定材料以次充好的赔付标准,明确追责机制。
|
||||
工地安全责任划分:施工工人人身安全由装修公司全权负责,业主不承担任何责任。
|
||||
工期与施工标准:延误工期赔付规则、施工不达标免费整改,整改费用由装修公司自行承担。
|
||||
(备注:保留原文所有提问维度、施工环节、询问细节不变,适当调整句式适配口播语感,不篡改每个环节必问的核心问题与避坑要点,完整保留原意)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文拆改、水电、瓷砖、吊顶、砌墙墙面、售后赔付的施工流程顺序排列,不打乱结构,贴合业主半包咨询询价的真实沟通逻辑,层层递进通俗易懂。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面提问话术改成抖音接地气口播大白话,不改变每个环节询问的项目、品牌、工艺、收费、责任划分等核心信息,全部细节原样保留。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解环节完整、节奏适中,不啰嗦不拖沓,适配短视频完播习惯。
|
||||
内容适配性:十大问题衔接自然,每个施工环节独立成段适配空镜分镜,直击半包业主不会询价、容易被低价套路、后期增项扯皮的核心痛点,逐条给到可直接照着问的实用话术。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修报价注意事项、评论区扣关键词领资料的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文真实吐槽语气,3 秒抓眼球,点破半包业主盲目报面积询价、被装修公司当成新手宰割的现状,瞬间引发准备半包装修业主共鸣。
|
||||
全程口语化大白话,小白一听就懂、可直接照搬拿去问装修公司,站业主立场拆解半包询价所有关键点,条理清晰干货满满,不生硬说教,贴合口播传播节奏。
|
||||
可微调句式语序,严禁篡改拆改、水电、瓷砖、吊顶、墙面、赔付责任等所有提问核心细节,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
如果你选择半包装修,千万别傻傻的问你家几平米要花多少钱?装修公司一听,哟,又来一个送钱的。记住,半包装修一定要问的是这 10 个问题,直接省下来好几万。
|
||||
第一,拆改问墙体拆除时要不要做切割,含不含垃圾清运,拆下来的旧门窗给你折扣多少钱?
|
||||
第二,水电,问水电是全改还是局改?电线是什么牌子,什么规格?水管又是什么牌子?壁厚多少?水电是走顶还是走地?点对点还是横平竖直?开关插座点位多少?包不包安装?
|
||||
第三,瓷砖,问出不出排版图,还要让瓦工现场复尺,确保落地。问包不包海棠角,全屋通铺要不要加钱?
|
||||
第四,吊顶,问用的是木龙骨还是轻钢龙骨?石膏板是什么牌子的?做单层还是做双层?七字拐、八字缝有没有做?
|
||||
第五,砌墙,问墙固用什么牌子,是油工刷还是开工就刷?挂网是局部还是全屋挂网?全挂要不要加钱?腻子的话,我只认国产一线品牌,其他我都不要。墙顶面我只要顺平就好,柜子后面、踢脚线、门口、窗口局部都要找平就行。乳胶漆用的是什么牌子,有没有刷底漆?是刷几遍,都要给我备注上。
|
||||
最后,装修用的材料,如果发现是以次充好,该怎么赔?工人安全是谁来负责?工期耽误了又该怎么赔?施工不达标,要不要整改?整改费用谁出?
|
||||
这些问题你不搞清楚,后期肯定扯皮。我整理了装修报价注意事项,评论区抠报价,拿去用
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近半包装修、报价询价主题,优先选工地恶搞、量房勘测、现场交底等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙体拆除、水电施工、吊顶造型、瓷砖铺贴、墙面基层等半包施工相关空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域的抖音 / 视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:选择半包装修、不懂怎么询价、容易被装修公司套路报价、不知道该重点问哪些问题的装修业主,围绕半包装修必问 10 大关键问题创作,按原文逻辑顺序排列,不随机抽取。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头询价痛点引入 + 半包 10 大必问问题干货 + 结尾资料领取引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:完整保留原文开头核心原意,仅轻微口语化微调,用扎心视角点出半包业主盲目询价容易被当成新手收割、多花冤枉钱的痛点,引出下文必问 10 个关键问题。
|
||||
中间核心(半包装修 10 大必问问题要点,文案适当调整修改,意思保持原意,按原文序号逻辑排列,不随机抽取):
|
||||
拆改环节要问清:墙体拆除是否做切割施工,包含垃圾清运与否,旧门窗拆除能抵扣多少费用。
|
||||
水电环节逐项确认:水电是全改还是局部改造,电线水管品牌规格、壁厚、走顶走地工艺都要问清,布线方式与开关插座点位安装也要明确。
|
||||
瓷砖施工提前敲定:是否出具排版图纸,瓦工现场复尺落地,海棠角施工、全屋通铺是否额外收费。
|
||||
吊顶工艺核对细节:龙骨选用木龙骨还是轻钢龙骨,石膏板品牌、单层双层工艺,七字拐八字缝防裂工序是否标配。
|
||||
砌墙墙面基层问明白:墙固品牌与涂刷节点,挂网局部还是全屋、全屋挂网是否加价。
|
||||
辅材品牌提前锁定:腻子只选国产一线品牌,墙顶面只做顺平,柜子及边角局部找平即可。
|
||||
乳胶漆明确标准:确认乳胶漆品牌、是否涂刷底漆、整体涂刷遍数,全部写进合同备注。
|
||||
材料品质约束条款:约定材料以次充好的赔付标准,明确追责机制。
|
||||
工地安全责任划分:施工工人人身安全由装修公司全权负责,业主不承担任何责任。
|
||||
工期与施工标准:延误工期赔付规则、施工不达标免费整改,整改费用由装修公司自行承担。
|
||||
(备注:保留原文所有提问维度、施工环节、询问细节不变,适当调整句式适配口播语感,不篡改每个环节必问的核心问题与避坑要点,完整保留原意)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:严格按原文拆改、水电、瓷砖、吊顶、砌墙墙面、售后赔付的施工流程顺序排列,不打乱结构,贴合业主半包咨询询价的真实沟通逻辑,层层递进通俗易懂。
|
||||
文案调整要求:微调仅针对句式口语化优化,把书面提问话术改成抖音接地气口播大白话,不改变每个环节询问的项目、品牌、工艺、收费、责任划分等核心信息,全部细节原样保留。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在 400-480 字,按每秒 4 个纯文字计算,对应时长 100-120s,讲解环节完整、节奏适中,不啰嗦不拖沓,适配短视频完播习惯。
|
||||
内容适配性:十大问题衔接自然,每个施工环节独立成段适配空镜分镜,直击半包业主不会询价、容易被低价套路、后期增项扯皮的核心痛点,逐条给到可直接照着问的实用话术。
|
||||
结尾范式:完整保留原文结尾原话,仅可轻微优化口语流畅度,不改动领取装修报价注意事项、评论区回复关键词领资料的核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文真实吐槽语气,3 秒抓眼球,点破半包业主盲目报面积询价、被装修公司当成新手宰割的现状,瞬间引发准备半包装修业主共鸣。
|
||||
全程口语化大白话,小白一听就懂、可直接照搬拿去问装修公司,站业主立场拆解半包询价所有关键点,条理清晰干货满满,不生硬说教,贴合口播传播节奏。
|
||||
可微调句式语序,严禁篡改拆改、水电、瓷砖、吊顶、墙面、赔付责任等所有提问核心细节,每句带标点规范断句,拆分大长句,适配口播表达习惯。
|
||||
【内置固定原文案】
|
||||
如果你选择半包装修,千万别傻傻的问你家几平米要花多少钱?装修公司一听,哟,又来一个送钱的。记住,半包装修一定要问的是这 10 个问题,直接省下来好几万。
|
||||
第一,拆改问墙体拆除时要不要做切割,含不含垃圾清运,拆下来的旧门窗给你折扣多少钱?
|
||||
第二,水电,问水电是全改还是局改?电线是什么牌子,什么规格?水管又是什么牌子?壁厚多少?水电是走顶还是走地?点对点还是横平竖直?开关插座点位多少?包不包安装?
|
||||
第三,瓷砖,问出不出排版图,还要让瓦工现场复尺,确保落地。问包不包海棠角,全屋通铺要不要加钱?
|
||||
第四,吊顶,问用的是木龙骨还是轻钢龙骨?石膏板是什么牌子的?做单层还是做双层?七字拐、八字缝有没有做?
|
||||
第五,砌墙,问墙固用什么牌子,是油工刷还是开工就刷?挂网是局部还是全屋挂网?全挂要不要加钱?腻子的话,我只认国产一线品牌,其他我都不要。墙顶面我只要顺平就好,柜子后面、踢脚线、门口、窗口局部都要找平就行。乳胶漆用的是什么牌子,有没有刷底漆?是刷几遍,都要给我备注上。
|
||||
最后,装修用的材料,如果发现是以次充好,该怎么赔?工人安全是谁来负责?工期耽误了又该怎么赔?施工不达标,要不要整改?整改费用谁出?
|
||||
这些问题你不搞清楚,后期肯定扯皮。我整理了装修报价注意事项,评论区回复报价,拿去用
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近半包装修、报价询价主题,优先选工地恶搞、量房勘测、现场交底等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选墙体拆除、水电施工、吊顶造型、瓷砖铺贴、墙面基层等半包施工相关空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 "等于" 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 "分镜时长" 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 "分镜文案" 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 "配音文案" 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 "5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
@@ -1,252 +1,252 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:预算有限、准备装修想省钱、容易乱花钱在没必要建材家具上的业主,严格围绕**装修最不值得花钱的8个地方**创作,每次自动打乱8个点位顺序,保留原意不改动核心信息。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机打乱8个省钱避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:原样保留原文开头结构和话术,仅可微调口语语气,不改动核心句意,直接引出8个不值得花钱的装修点位。
|
||||
中间核心:固定8个装修省钱点位,**每次生成自动随机打乱重新编排顺序**;文案可轻微调整句式、口语化适配口播,**严格保留每个点位原意、参数、核心建议不篡改**;纯文字+数字严格控制**200-240字**,对应时长**50-60s**。
|
||||
结尾范式:尽可能原样保留原文结尾结构,仅可微调引导话术,保持领资料抠关键词的原意不变。
|
||||
【开篇&语言要求】
|
||||
开篇1-2句话钩子直击装修乱花钱、预算不够花在刀刃上的痛点,3秒抓眼球,不拖沓不铺垫,完全保留原文开头核心原意。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改8个省钱点位的品牌、规格、参数、选购逻辑,每句必须带标点断句。
|
||||
【细节固定要求】
|
||||
沿用原有分镜逻辑、人物出镜/空镜配比规则,总分镜数量、单镜时长仍遵循3-8秒保留两位小数;严格按每秒4字核算时长,纯文字只扣标点、含汉字数字统计。
|
||||
【内置固定原文案】
|
||||
装修最不值得花钱的8个地方,预算有限一定要记牢!
|
||||
1.瓷砖不用追品牌,有3C认证,800×800性价比最高。
|
||||
2.电线选BV线,大品牌基础款,耐用又省钱。
|
||||
3.地漏要用得久,直接选纯铜防臭款更靠谱。
|
||||
4.插座没技术含量,大品牌基础款就足够用。
|
||||
5.乳胶漆别交智商税,大品牌基础款带十环认证就行。
|
||||
6.灯具溢价高,搜广东中山灯具,便宜款式还多。
|
||||
7.床不用看品牌,舒不舒服关键看床垫怎么样。
|
||||
8.卧室门看材质,选4.5公分以上实木复合烤漆门。
|
||||
准备装修的朋友,回避坑领取装修避坑省钱手册!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴合装修省钱避坑主题)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,匹配不上选近似主材、家装类空镜
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分镜文案=配音文案,必须带标点断句,不做大长句;每个分镜文案纯文字(含数字、扣标点)严格12-32字。
|
||||
分镜时长计算规则:纯文字含汉字+阿拉伯数字,只扣除标点,字数÷4,保留两位小数,单镜时长严控3-8秒。
|
||||
type规则:segment=人物出镜,empty_shot=选上方素材库标题。
|
||||
硬性约束:全程总纯文字200-240字、总时长50-60s;每次随机打乱8个点位顺序,不篡改原文参数和选购逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:预算有限、准备装修想省钱、容易乱花钱在没必要建材家具上的业主,严格围绕**装修最不值得花钱的8个地方**创作,每次自动打乱8个点位顺序,保留原意不改动核心信息。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机打乱8个省钱避坑干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
【平台适配】
|
||||
竖屏9:16拍摄
|
||||
【核心强制规则】
|
||||
开头范式:原样保留原文开头结构和话术,仅可微调口语语气,不改动核心句意,直接引出8个不值得花钱的装修点位。
|
||||
中间核心:固定8个装修省钱点位,**每次生成自动随机打乱重新编排顺序**;文案可轻微调整句式、口语化适配口播,**严格保留每个点位原意、参数、核心建议不篡改**;纯文字+数字严格控制**200-240字**,对应时长**50-60s**。
|
||||
结尾范式:尽可能原样保留原文结尾结构,仅可微调引导话术,保持领资料回复关键词的原意不变。
|
||||
【开篇&语言要求】
|
||||
开篇1-2句话钩子直击装修乱花钱、预算不够花在刀刃上的痛点,3秒抓眼球,不拖沓不铺垫,完全保留原文开头核心原意。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场,贴合原文口语化风格。
|
||||
可微调句式,不得篡改8个省钱点位的品牌、规格、参数、选购逻辑,每句必须带标点断句。
|
||||
【细节固定要求】
|
||||
沿用原有分镜逻辑、人物出镜/空镜配比规则,总分镜数量、单镜时长仍遵循3-8秒保留两位小数;严格按每秒4字核算时长,纯文字只扣标点、含汉字数字统计。
|
||||
【内置固定原文案】
|
||||
装修最不值得花钱的8个地方,预算有限一定要记牢!
|
||||
1.瓷砖不用追品牌,有3C认证,800×800性价比最高。
|
||||
2.电线选BV线,大品牌基础款,耐用又省钱。
|
||||
3.地漏要用得久,直接选纯铜防臭款更靠谱。
|
||||
4.插座没技术含量,大品牌基础款就足够用。
|
||||
5.乳胶漆别交智商税,大品牌基础款带十环认证就行。
|
||||
6.灯具溢价高,搜广东中山灯具,便宜款式还多。
|
||||
7.床不用看品牌,舒不舒服关键看床垫怎么样。
|
||||
8.卧室门看材质,选4.5公分以上实木复合烤漆门。
|
||||
准备装修的朋友,回避坑领取装修避坑省钱手册!
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,贴合装修省钱避坑主题)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,匹配不上选近似主材、家装类空镜
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分镜文案=配音文案,必须带标点断句,不做大长句;每个分镜文案纯文字(含数字、扣标点)严格12-32字。
|
||||
分镜时长计算规则:纯文字含汉字+阿拉伯数字,只扣除标点,字数÷4,保留两位小数,单镜时长严控3-8秒。
|
||||
type规则:segment=人物出镜,empty_shot=选上方素材库标题。
|
||||
硬性约束:全程总纯文字200-240字、总时长50-60s;每次随机打乱8个点位顺序,不篡改原文参数和选购逻辑。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “贴砖恶搞 - 恶搞开篇”,
|
||||
“voiceover”: “瓦工进场只盯海棠角,后期必踩大坑,7 个细节记牢”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “瓦工一来先交代这 7 个细节,师傅绝对不敢糊弄你”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “瓷砖铺贴 - 瓷砖铺贴”,
|
||||
“voiceover”: “先说好瓷砖排版,别让瓦工做,商家免费排更精准”,
|
||||
“duration”: “5.00s”
|
||||
}
|
||||
]
|
||||
@@ -1,245 +1,245 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域抖音、视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定准备新房装修、不懂安装行业隐形套路、容易被师傅隐瞒细节后期返工踩坑的业主,围绕马桶、卫生间吊顶、油烟机、橱柜、浴室柜5 大安装隐形套路创作,保留原文人设代入式口吻、原意不变,句式可口语化微调。
|
||||
(二)脚本类型
|
||||
装修安装避坑共情口播短视频脚本,结构固定:完整保留原文开头原话引入 + 5 大安装套路干货微调改写 + 完整保留原文结尾福利引导,不篡改核心逻辑,不增减坑位数量。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,直击装修行业人性自私贪婪、师傅刻意隐瞒施工细节的痛点,用举例代入方式引出下文 5 大安装套路。
|
||||
中间核心(5 大装修安装隐形套路,文案适当调整修改,意思保持原意,固定全部 5 条不删减):
|
||||
1、马桶安装师傅不会主动提醒马桶下水管边缘刷防水,也不告知黑色法兰圈易老化反味,后期漏水、反味再让业主花钱维修。
|
||||
2、卫生间吊顶师傅发现没装止逆阀也不会提醒,直接把排风管暗藏吊顶内,后期出现洗澡灌冷风、厨卫串味甚至鸟巢遗留隐患。
|
||||
3、油烟机安装师傅不会主动推荐升降烟机支架,故意隐瞒预留缝隙问题,等吊柜装好留缝难看,再上门更换额外收取安装费用。
|
||||
4、橱柜安装师傅不会主动给板材切割断面做收边条封边,怕增加工序、被扣尾款,长期使用板材受潮发霉,业主很难找到真实原因。
|
||||
5、浴室柜安装师傅不会提前提醒业主备好下水器,直接简易插接下水管敷衍完工,避免等待采购、安装适配漏水带来的后续麻烦。
|
||||
(备注:保留原文 5 个套路每一条的人设代入、隐瞒动机、后期隐患、师傅心理逻辑完整不变;仅适当调整句式、理顺口播语感,不删减关键细节、不篡改原意、不改变每条避坑核心)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
文案调整要求:仅做口语化顺滑优化,把书面表述改成抖音接地气大白话,保留每一类安装师傅的隐瞒心理、省略工序、后期造成的居住隐患完整不变,不新增、不删减套路点。
|
||||
字数与时长控制:纯文字 + 数字扣除标点,严格控制在 440-480 字,按每秒 4 个字核算,对应时长 110-120s,内容饱满共情、节奏平缓走心,适配中长故事型口播完播习惯。
|
||||
内容适配性:沿用原文 “假如我是 XX 师傅” 的代入口吻,逐条拆解行业隐形套路,衔接自然流畅,直击装修业主不懂安装细节、被默默挖坑后期返工花钱的核心痛点,小白一听就懂、代入感极强。
|
||||
结尾范式
|
||||
完整保留原文结尾原话,只可轻微口语化微调,不改动装修套路深、整理全流程避坑手册、评论扣关键词领取、提前避坑少走弯路的福利引导核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头原话,直击人性套路,3 秒抓住装修业主好奇心;
|
||||
全程保持原文第一人称代入共情口吻,接地气、写实走心,站业主视角拆解行业内幕,不生硬说教、不夸张造谣;
|
||||
可微调语序、精简冗余表述,严禁改动 5 大安装套路的隐瞒细节、后期隐患、师傅心理逻辑;语句合理断句,适配口播节奏,规避超长句子。
|
||||
【内置固定原文案】
|
||||
人性的自私和贪婪在装修这件事上发挥得淋漓尽致。我举几个例子你就懂了。
|
||||
假如我是安装马桶的师傅,我不会提醒你,马桶下水管边缘得刷一层防水,防止漏水。我要是说了,这活儿很可能还得我干,我图啥?我更不会告诉你那种黑色法兰圈时间一长就老化,卫生间总反味。我直接给你装上,等你家臭了你再花钱找人换呗。
|
||||
假如我是安装卫生间吊顶的师傅,我不会提醒你家没装止逆阀,我知道你没买,我要是提了,今天这活儿可能就干不完了,我就把排风管往吊顶里面一扔,反正你也看不见。等你住进去洗澡灌冷风,卫生间串味,甚至小鸟在上面筑巢,你后悔都来不及。
|
||||
假如我是安装油烟机的师傅,我一定不会提醒你烟机支架可以换成升降的。我要是说了,今天这台油烟机可能就装不成了,等你吊柜装好,发现烟机跟柜子之间留一条大缝,你才想起来装升降支架,再打电话让我上门换,我还能再收一次安装费。
|
||||
假如我是安装橱柜的师傅,我一定不会提,给你板材切割的断面要用收边条封上。我要是说了,活儿多了还得我干,搞不好还因为这点小事扣我尾款,我还是不说的好,等以后板材受潮发霉,你也想不到是因为没封边造成的。
|
||||
假如我是安装浴室柜的师傅,我一定不会提醒你提前买好下水器,我直接把下水管给你塞进去就完事。我要是说了,还得等你去买,买回来我还得帮你装,万一装不上或者漏水,又是一堆麻烦,何必呢?
|
||||
装修套路深,想省心不存在的。我整理了全流程避坑手册,抠手册直接拿走,提前了解,少走弯路。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(优先选恶搞开篇、施工翻车镜、毛坯全景等贴近装修安装套路、避坑主题)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分点阐述全部用空镜,空镜素材库标题与文案内容需精准匹配,匹配不到则选主材安装、柜体木作、厨卫相关近似空镜。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分镜文案 = 配音文案,必须带标点断句,规避大长句;单条分镜纯文字(含数字、不含标点)严格控制 12-32 字,超长句强制拆分多镜,语句通顺完整。
|
||||
字数时长统一规范:全篇文案纯文字 + 数字扣除标点严控 440-480 字、时长 110-120s;单分镜严格按每秒 4 个纯文字计算,只统计汉字 + 数字、扣除标点,时长保留两位小数,单镜时长强制锁定 3-8 秒,超出必须拆句重分镜。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方素材库选匹配标题。
|
||||
人物出镜画面允许句子语意延伸到下一分镜;空镜必须贴合当前配音文案主题。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "新建墙体垂直找平 - 新建砌筑",
|
||||
"voiceover": "砌墙完工之后,一定要停工静置等待 5 天。",
|
||||
"duration": "4.25s"
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装 / 装修领域抖音、视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定准备新房装修、不懂安装行业隐形套路、容易被师傅隐瞒细节后期返工踩坑的业主,围绕马桶、卫生间吊顶、油烟机、橱柜、浴室柜5 大安装隐形套路创作,保留原文人设代入式口吻、原意不变,句式可口语化微调。
|
||||
(二)脚本类型
|
||||
装修安装避坑共情口播短视频脚本,结构固定:完整保留原文开头原话引入 + 5 大安装套路干货微调改写 + 完整保留原文结尾福利引导,不篡改核心逻辑,不增减坑位数量。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式
|
||||
完整保留原文开头原话,只可轻微口语化微调,不改动核心原意,直击装修行业人性自私贪婪、师傅刻意隐瞒施工细节的痛点,用举例代入方式引出下文 5 大安装套路。
|
||||
中间核心(5 大装修安装隐形套路,文案适当调整修改,意思保持原意,固定全部 5 条不删减):
|
||||
1、马桶安装师傅不会主动提醒马桶下水管边缘刷防水,也不告知黑色法兰圈易老化反味,后期漏水、反味再让业主花钱维修。
|
||||
2、卫生间吊顶师傅发现没装止逆阀也不会提醒,直接把排风管暗藏吊顶内,后期出现洗澡灌冷风、厨卫串味甚至鸟巢遗留隐患。
|
||||
3、油烟机安装师傅不会主动推荐升降烟机支架,故意隐瞒预留缝隙问题,等吊柜装好留缝难看,再上门更换额外收取安装费用。
|
||||
4、橱柜安装师傅不会主动给板材切割断面做收边条封边,怕增加工序、被扣尾款,长期使用板材受潮发霉,业主很难找到真实原因。
|
||||
5、浴室柜安装师傅不会提前提醒业主备好下水器,直接简易插接下水管敷衍完工,避免等待采购、安装适配漏水带来的后续麻烦。
|
||||
(备注:保留原文 5 个套路每一条的人设代入、隐瞒动机、后期隐患、师傅心理逻辑完整不变;仅适当调整句式、理顺口播语感,不删减关键细节、不篡改原意、不改变每条避坑核心)
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
文案调整要求:仅做口语化顺滑优化,把书面表述改成抖音接地气大白话,保留每一类安装师傅的隐瞒心理、省略工序、后期造成的居住隐患完整不变,不新增、不删减套路点。
|
||||
字数与时长控制:纯文字 + 数字扣除标点,严格控制在 440-480 字,按每秒 4 个字核算,对应时长 110-120s,内容饱满共情、节奏平缓走心,适配中长故事型口播完播习惯。
|
||||
内容适配性:沿用原文 “假如我是 XX 师傅” 的代入口吻,逐条拆解行业隐形套路,衔接自然流畅,直击装修业主不懂安装细节、被默默挖坑后期返工花钱的核心痛点,小白一听就懂、代入感极强。
|
||||
结尾范式
|
||||
完整保留原文结尾原话,只可轻微口语化微调,不改动装修套路深、整理全流程避坑手册、评论回复关键词领取、提前避坑少走弯路的福利引导核心逻辑。
|
||||
【开篇 & 语言要求】
|
||||
开篇完整沿用原文开头原话,直击人性套路,3 秒抓住装修业主好奇心;
|
||||
全程保持原文第一人称代入共情口吻,接地气、写实走心,站业主视角拆解行业内幕,不生硬说教、不夸张造谣;
|
||||
可微调语序、精简冗余表述,严禁改动 5 大安装套路的隐瞒细节、后期隐患、师傅心理逻辑;语句合理断句,适配口播节奏,规避超长句子。
|
||||
【内置固定原文案】
|
||||
人性的自私和贪婪在装修这件事上发挥得淋漓尽致。我举几个例子你就懂了。
|
||||
假如我是安装马桶的师傅,我不会提醒你,马桶下水管边缘得刷一层防水,防止漏水。我要是说了,这活儿很可能还得我干,我图啥?我更不会告诉你那种黑色法兰圈时间一长就老化,卫生间总反味。我直接给你装上,等你家臭了你再花钱找人换呗。
|
||||
假如我是安装卫生间吊顶的师傅,我不会提醒你家没装止逆阀,我知道你没买,我要是提了,今天这活儿可能就干不完了,我就把排风管往吊顶里面一扔,反正你也看不见。等你住进去洗澡灌冷风,卫生间串味,甚至小鸟在上面筑巢,你后悔都来不及。
|
||||
假如我是安装油烟机的师傅,我一定不会提醒你烟机支架可以换成升降的。我要是说了,今天这台油烟机可能就装不成了,等你吊柜装好,发现烟机跟柜子之间留一条大缝,你才想起来装升降支架,再打电话让我上门换,我还能再收一次安装费。
|
||||
假如我是安装橱柜的师傅,我一定不会提,给你板材切割的断面要用收边条封上。我要是说了,活儿多了还得我干,搞不好还因为这点小事扣我尾款,我还是不说的好,等以后板材受潮发霉,你也想不到是因为没封边造成的。
|
||||
假如我是安装浴室柜的师傅,我一定不会提醒你提前买好下水器,我直接把下水管给你塞进去就完事。我要是说了,还得等你去买,买回来我还得帮你装,万一装不上或者漏水,又是一堆麻烦,何必呢?
|
||||
装修套路深,想省心不存在的。我整理了全流程避坑手册,回复手册直接拿走,提前了解,少走弯路。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(优先选恶搞开篇、施工翻车镜、毛坯全景等贴近装修安装套路、避坑主题)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分点阐述全部用空镜,空镜素材库标题与文案内容需精准匹配,匹配不到则选主材安装、柜体木作、厨卫相关近似空镜。
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜。
|
||||
分镜文案 = 配音文案,必须带标点断句,规避大长句;单条分镜纯文字(含数字、不含标点)严格控制 12-32 字,超长句强制拆分多镜,语句通顺完整。
|
||||
字数时长统一规范:全篇文案纯文字 + 数字扣除标点严控 440-480 字、时长 110-120s;单分镜严格按每秒 4 个纯文字计算,只统计汉字 + 数字、扣除标点,时长保留两位小数,单镜时长强制锁定 3-8 秒,超出必须拆句重分镜。
|
||||
type 定义:segment = 人物出镜;empty_shot = 从上方素材库选匹配标题。
|
||||
人物出镜画面允许句子语意延伸到下一分镜;空镜必须贴合当前配音文案主题。
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为配音文案纯文字字数 ÷4,严格控制在 3-8 秒,可以是两位小数)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "新建墙体垂直找平 - 新建砌筑",
|
||||
"voiceover": "砌墙完工之后,一定要停工静置等待 5 天。",
|
||||
"duration": "4.25s"
|
||||
}
|
||||
]
|
||||
@@ -1,281 +1,281 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将进行厨卫防水施工、担心工人偷工减料、怕后期漏水返工的业主,严格围绕防水施工标准创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机4点防水干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
|
||||
【平台适配&字数时长精准定义】
|
||||
竖屏9:16拍摄,口语化口播,严格按**每秒4个纯文字**计算时长。
|
||||
文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算。
|
||||
每句配音必须带标点断句;单句不含标点(含数字)字数12–32字,对应单镜时长3–8秒。
|
||||
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:防水】,谁要是给你一上来就【错误操作】,你就直接撵走他。你以为他是帮你【表面好处:赶工期】,其实他就是图【错误目的:省事儿、不想多花功夫】。下面这8点一定要做到位,少一步都不行!”为核心句式,用警示性语气点出常见坑,引出下文要点。
|
||||
中间核心(8个装修防水要点,文案可以修改,意思保持原意,可随机抽取4个重编序号): 1. 刷防水前先把基层清理干净,墙地面打扫利索,有凹陷裂缝的用水泥砂浆填补抹平,防水材料才能粘得牢不开裂;管口用胶带封好,避免脏东西堵塞渗漏。 2. 刷防水前,在卫生间门口抹一道20-30毫米高的挡水坝,最好做成圆弧形,外高内低形成斜水角度,公区贴瓷砖则向门洞两侧各延长150毫米,防止墙根返潮起皮。 3. 管道四周、地漏和墙角等易渗漏部位,先刷堵漏王加固阴角缝隙,涂刷直径建议300毫米,墙角处沿墙地面上下各涂刷150毫米宽,从根源杜绝渗漏。 4. 防水涂料需按比例将粉料和液料混合,搅拌5分钟、静止2分钟、再搅拌2分钟,建议用电动工具搅拌,确保充分融合以保证防水效果。 5. 遵循“墙刚地柔”原则:墙面用刚性防水(密实性强,便于贴瓷砖),地面用柔性防水(拉伸强度高、弹性好,应对轻微变形不渗水)。 6. 涂刷时先重点处理管道四周和墙角,再大面积十字交叉涂刷(横竖各一遍),淋浴区涂刷高度不低于1.8米,干区浴室柜位置不低于1.2米,门口不低于30公分,地面防水上返墙面200毫米以上。 7. 第一遍防水完全干燥后,再刷第二遍,两遍涂刷方向相互垂直,避免遗漏和针气孔缺陷,做到双重防护。 8. 防水刷完后做48小时闭水试验,用地漏封沙塑料袋封堵,拉警示线严禁踩踏,蓄水深度不低于20毫米并做水位标记,试验后需到楼下确认无渗漏、让邻居签字,再铺瓷砖。
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑指南】,抠【核心关键词:防水】直接拿走,里面全是实用干货,需要的可以找我要!
|
||||
|
||||
【字数&时长硬约束】
|
||||
总字数:不含标点、含数字,严格控制在400–480字。
|
||||
总时长:总无标点字数÷4,精确两位小数,必须卡在100–120秒。
|
||||
单句时长:单句无标点字数÷4,保留两位小数,强制3–8秒,超出必须拆分句子多分镜。
|
||||
句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
|
||||
【开篇&语言要求】
|
||||
开篇1–2句话钩子,直击工人偷工减料痛点,3秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场。
|
||||
可微调句式,不得篡改原文施工流程、尺寸、时间等核心数字数据,每句必须带标点断句。
|
||||
|
||||
【细节固定要求】
|
||||
结尾必须固定话术:我整理了装修全流程避坑指南,抠防水直接拿走。
|
||||
总分镜数量固定12–20个,每个分镜时长3–8秒,可保留两位小数。
|
||||
|
||||
【分镜固定结构规则】
|
||||
开篇分镜固定顺序:网红开篇(优先恶搞开篇/施工翻车镜,贴合防水主题)+ 人物出镜 + 空镜补充。
|
||||
中间4点干货全部用empty_shot空镜。
|
||||
结尾固定人物出镜收尾。
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
人物出镜文案可跨分镜延伸,不用单句卡死。
|
||||
空镜素材优先匹配当前文案防水内容,匹配不到选同类近似空镜。
|
||||
单分镜时长严格按:该句无标点含数字总字数÷4 计算,保留两位小数。
|
||||
总分镜总时长 = 全文无标点含数字总字数 ÷4。
|
||||
|
||||
【内置固定原文案】
|
||||
新房装修刷防水,谁要是给你一上来就开刷,你就直接撵走他。你以为他是帮你赶工期,其实他就是图省事儿,不想多花功夫。下面这 8 点一定要做到位,少一步都不行!
|
||||
第一,刷防水前先把基层清理干净,墙地面打扫利索,有凹陷裂缝的用水泥砂浆填补抹平,防水材料才能粘得牢不开裂。管口那块用胶带封好,别让脏东西掉进去,避免后期堵塞渗漏。
|
||||
第二,刷防水前,记得在卫生间门口抹一道 20 到 30 毫米高的挡水坝,最好做成圆弧形,外高内低形成斜水角度,这样水不会顺着砂浆渗到门外,省得以后两边墙根返潮起皮。如果公区贴瓷砖,挡水坝还要向门洞两侧各延长 150 毫米哦。
|
||||
第三,管道四周、地漏和墙角这些容易漏的地方,记得先刷上堵漏王,把阴角缝隙加固好,涂刷直径建议达到 300 毫米,墙角处沿墙地面上下各涂刷 150 毫米宽,从根源杜绝渗漏隐患。
|
||||
第四,防水涂料不是随便搅两下就能用的,靠谱的做法是先把粉料和液料按比例混合,搅拌 5 分钟,静止 2 分钟,再搅拌 2 分钟,让它充分融合,这样防水效果才能拉满,最好用电动工具搅拌更均匀哦。
|
||||
第五,墙面用刚性防水,刚性材料密实性强,后期贴瓷砖才能挂得住;地面用柔性防水,拉伸强度高、弹性更好,能应对轻微变形,不会渗水,这就是装修里常说的 “墙刚地柔”。
|
||||
第六,刷的时候先重点处理管道四周和墙角,再大面积涂刷,横竖各刷一遍形成十字交叉,涂刷厚度要达标。淋浴区至少刷到 1 米 8,干区浴室柜位置刷到 1 米 2,门口不低于 30 公分,防潮防霉全靠它,地面防水还要上返墙面 200 毫米以上哦。
|
||||
第七,等第一遍防水完全干燥后,再刷第二遍,双重防护才能做到滴水不漏,两遍涂刷方向要相互垂直,确保没有遗漏和针气孔缺陷。
|
||||
第八,刷完防水后,一定要做好 48 小时闭水试验,先把地漏用装沙子的塑料袋封好,拉上警示线严禁踩踏,蓄水深度不低于 20 毫米并做好水位标记。试验结束后,你要亲自到楼下看看漏没漏,让邻居签个字确认没问题,再铺瓷砖,避免后期返工扯皮。
|
||||
准备新房装修的朋友,我整理了一份装修全流程避坑指南,抠防水直接拿走,里面全是实用干货,需要的可以找我要!
|
||||
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜结构】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近主题)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
"分镜文案"等于"配音文案",每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,则用多个分镜
|
||||
每个分镜的"分镜时长"为{"分镜文案"的字数(含数字,不含标点符号)/4},严格控制在3-8秒,可以是两位小数,如 3.25 秒
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
配音文案必须要有标点符号断句,避免大长句,如:装修报价别只看总价,漏一项,后期就得多花好几万。
|
||||
禁止总字数偏离400–480(含数字,不含标点符号)、总时长偏离100–120秒。
|
||||
禁止篡改原文防水尺寸、时间、工艺核心数据。
|
||||
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:即将进行厨卫防水施工、担心工人偷工减料、怕后期漏水返工的业主,严格围绕防水施工标准创作。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头痛点 + 随机4点防水干货 + 结尾引导,无多余内容,无重复,无冗余。
|
||||
|
||||
【平台适配&字数时长精准定义】
|
||||
竖屏9:16拍摄,口语化口播,严格按**每秒4个纯文字**计算时长。
|
||||
文字统计硬性定义:**纯文字包含汉字、阿拉伯数字,只扣除标点符号**,所有字数、时长全部按这个口径计算。
|
||||
每句配音必须带标点断句;单句不含标点(含数字)字数12–32字,对应单镜时长3–8秒。
|
||||
|
||||
【核心强制规则】
|
||||
开头范式:以“新房装修【核心场景:防水】,谁要是给你一上来就【错误操作】,你就直接撵走他。你以为他是帮你【表面好处:赶工期】,其实他就是图【错误目的:省事儿、不想多花功夫】。下面这8点一定要做到位,少一步都不行!”为核心句式,用警示性语气点出常见坑,引出下文要点。
|
||||
中间核心(8个装修防水要点,文案可以修改,意思保持原意,可随机抽取4个重编序号): 1. 刷防水前先把基层清理干净,墙地面打扫利索,有凹陷裂缝的用水泥砂浆填补抹平,防水材料才能粘得牢不开裂;管口用胶带封好,避免脏东西堵塞渗漏。 2. 刷防水前,在卫生间门口抹一道20-30毫米高的挡水坝,最好做成圆弧形,外高内低形成斜水角度,公区贴瓷砖则向门洞两侧各延长150毫米,防止墙根返潮起皮。 3. 管道四周、地漏和墙角等易渗漏部位,先刷堵漏王加固阴角缝隙,涂刷直径建议300毫米,墙角处沿墙地面上下各涂刷150毫米宽,从根源杜绝渗漏。 4. 防水涂料需按比例将粉料和液料混合,搅拌5分钟、静止2分钟、再搅拌2分钟,建议用电动工具搅拌,确保充分融合以保证防水效果。 5. 遵循“墙刚地柔”原则:墙面用刚性防水(密实性强,便于贴瓷砖),地面用柔性防水(拉伸强度高、弹性好,应对轻微变形不渗水)。 6. 涂刷时先重点处理管道四周和墙角,再大面积十字交叉涂刷(横竖各一遍),淋浴区涂刷高度不低于1.8米,干区浴室柜位置不低于1.2米,门口不低于30公分,地面防水上返墙面200毫米以上。 7. 第一遍防水完全干燥后,再刷第二遍,两遍涂刷方向相互垂直,避免遗漏和针气孔缺陷,做到双重防护。 8. 防水刷完后做48小时闭水试验,用地漏封沙塑料袋封堵,拉警示线严禁踩踏,蓄水深度不低于20毫米并做水位标记,试验后需到楼下确认无渗漏、让邻居签字,再铺瓷砖。
|
||||
结尾范式:准备新房装修的朋友,我整理了一份【相关福利:装修全流程避坑指南】,回复【核心关键词:防水】直接拿走,里面全是实用干货,需要的可以找我要!
|
||||
|
||||
【字数&时长硬约束】
|
||||
总字数:不含标点、含数字,严格控制在400–480字。
|
||||
总时长:总无标点字数÷4,精确两位小数,必须卡在100–120秒。
|
||||
单句时长:单句无标点字数÷4,保留两位小数,强制3–8秒,超出必须拆分句子多分镜。
|
||||
句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
|
||||
【开篇&语言要求】
|
||||
开篇1–2句话钩子,直击工人偷工减料痛点,3秒抓眼球,不拖沓不铺垫。
|
||||
全程口语化大白话,小白易懂,不生硬说教,站业主共情立场。
|
||||
可微调句式,不得篡改原文施工流程、尺寸、时间等核心数字数据,每句必须带标点断句。
|
||||
|
||||
【细节固定要求】
|
||||
结尾必须固定话术:我整理了装修全流程避坑指南,回复防水直接拿走。
|
||||
总分镜数量固定12–20个,每个分镜时长3–8秒,可保留两位小数。
|
||||
|
||||
【分镜固定结构规则】
|
||||
开篇分镜固定顺序:网红开篇(优先恶搞开篇/施工翻车镜,贴合防水主题)+ 人物出镜 + 空镜补充。
|
||||
中间4点干货全部用empty_shot空镜。
|
||||
结尾固定人物出镜收尾。
|
||||
type为segment=人物出镜;type为empty_shot=从下方内置素材库选匹配标题。
|
||||
人物出镜文案可跨分镜延伸,不用单句卡死。
|
||||
空镜素材优先匹配当前文案防水内容,匹配不到选同类近似空镜。
|
||||
单分镜时长严格按:该句无标点含数字总字数÷4 计算,保留两位小数。
|
||||
总分镜总时长 = 全文无标点含数字总字数 ÷4。
|
||||
|
||||
【内置固定原文案】
|
||||
新房装修刷防水,谁要是给你一上来就开刷,你就直接撵走他。你以为他是帮你赶工期,其实他就是图省事儿,不想多花功夫。下面这 8 点一定要做到位,少一步都不行!
|
||||
第一,刷防水前先把基层清理干净,墙地面打扫利索,有凹陷裂缝的用水泥砂浆填补抹平,防水材料才能粘得牢不开裂。管口那块用胶带封好,别让脏东西掉进去,避免后期堵塞渗漏。
|
||||
第二,刷防水前,记得在卫生间门口抹一道 20 到 30 毫米高的挡水坝,最好做成圆弧形,外高内低形成斜水角度,这样水不会顺着砂浆渗到门外,省得以后两边墙根返潮起皮。如果公区贴瓷砖,挡水坝还要向门洞两侧各延长 150 毫米哦。
|
||||
第三,管道四周、地漏和墙角这些容易漏的地方,记得先刷上堵漏王,把阴角缝隙加固好,涂刷直径建议达到 300 毫米,墙角处沿墙地面上下各涂刷 150 毫米宽,从根源杜绝渗漏隐患。
|
||||
第四,防水涂料不是随便搅两下就能用的,靠谱的做法是先把粉料和液料按比例混合,搅拌 5 分钟,静止 2 分钟,再搅拌 2 分钟,让它充分融合,这样防水效果才能拉满,最好用电动工具搅拌更均匀哦。
|
||||
第五,墙面用刚性防水,刚性材料密实性强,后期贴瓷砖才能挂得住;地面用柔性防水,拉伸强度高、弹性更好,能应对轻微变形,不会渗水,这就是装修里常说的 “墙刚地柔”。
|
||||
第六,刷的时候先重点处理管道四周和墙角,再大面积涂刷,横竖各刷一遍形成十字交叉,涂刷厚度要达标。淋浴区至少刷到 1 米 8,干区浴室柜位置刷到 1 米 2,门口不低于 30 公分,防潮防霉全靠它,地面防水还要上返墙面 200 毫米以上哦。
|
||||
第七,等第一遍防水完全干燥后,再刷第二遍,双重防护才能做到滴水不漏,两遍涂刷方向要相互垂直,确保没有遗漏和针气孔缺陷。
|
||||
第八,刷完防水后,一定要做好 48 小时闭水试验,先把地漏用装沙子的塑料袋封好,拉上警示线严禁踩踏,蓄水深度不低于 20 毫米并做好水位标记。试验结束后,你要亲自到楼下看看漏没漏,让邻居签个字确认没问题,再铺瓷砖,避免后期返工扯皮。
|
||||
准备新房装修的朋友,我整理了一份装修全流程避坑指南,回复防水直接拿走,里面全是实用干货,需要的可以找我要!
|
||||
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜结构】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近主题)+ 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有2段人物出镜
|
||||
"分镜文案"等于"配音文案",每段分镜的分镜文案字数严格控制在12-32个字,含数字,不含标点符号。文案一个分镜说不完,则用多个分镜
|
||||
每个分镜的"分镜时长"为{"分镜文案"的字数(含数字,不含标点符号)/4},严格控制在3-8秒,可以是两位小数,如 3.25 秒
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
配音文案必须要有标点符号断句,避免大长句,如:装修报价别只看总价,漏一项,后期就得多花好几万。
|
||||
禁止总字数偏离400–480(含数字,不含标点符号)、总时长偏离100–120秒。
|
||||
禁止篡改原文防水尺寸、时间、工艺核心数据。
|
||||
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在12-32个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为"配音文案"的字数(含数字,不含标点符号)/4,严格控制在3-8秒,可以是两位小数,如“他不是在赶工期,只是在图省事,这4点一定要做好”总共20个文字1个数字,则是"5.25s")
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"type": "empty_shot",
|
||||
"scene": "防水翻车漏水",
|
||||
"voiceover": "新房装修刷防水,一上来就开刷的工人,直接撵走别客气!",
|
||||
"duration": "5.75s"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "segment",
|
||||
"scene": "人物出镜",
|
||||
"voiceover": "他不是在赶工期,只是在图省事,这 4 点一定要做好。",
|
||||
"duration": "5.25s"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "empty_shot",
|
||||
"scene": "卫生间基层清理 - 防水施工",
|
||||
"voiceover": "第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。",
|
||||
"duration": "5.50s"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,280 +1,280 @@
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备装修阳台、容易被网红款式忽悠、盲目跟风装不实用设施,后期后悔返工、浪费钱的装修业主,围绕阳台装修14个坑,每次随机抽取5个重新编排顺序,创作避坑口播内容,贴合老装修人干货分享口吻。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头阳台装修避坑警示引入 + 随机5个阳台装修坑干货拆解 + 结尾避坑手册引导,无多余内容,无重复,无冗余,不增减坑点数量。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:
|
||||
完整保留原文开头核心原意,仅轻微口语化微调,用老装修人接地气的警示语气,点出“阳台装错东西谁装谁后悔”的核心痛点,结合20多年装修经验增强说服力,自然引出下文5个阳台装修坑,不篡改、不新增、不删减开头核心话术。
|
||||
中间核心(阳台装修5个避坑要点,从14个原始坑中随机抽取5个,重新编排顺序,文案适当调整修改,意思保持原意,可口语顺滑润色):
|
||||
(备注:每次生成均从14个原始坑中随机抽取5个,自主打乱排列顺序,不固定组合、不固定顺序;保留每个坑的核心原意、避坑逻辑、推荐方案、隐患后果不变,适当调整句式让口语化更贴合口播,不篡改任何核心细节)
|
||||
14个阳台装修原始坑点汇总(供随机抽取,每次选5个):
|
||||
1、阳台洗衣柜千万别装带搓衣板的,中看不中用,后期易积污垢难清理,推荐石英石台面加陶瓷盆,耐用抗造。
|
||||
2、千万别装窗台石,多为岗石(假石英石),易留刮痕,推荐直接用地砖铺贴,更耐磨、使用寿命更长。
|
||||
3、不推荐阳台做吊顶,费钱还压层高,铝扣板吊顶显小家子气,推荐刷乳胶漆,省钱又简洁。
|
||||
4、不推荐洗烘一体机,烘干功能鸡肋,烘出衣服皱巴巴,推荐独立洗衣机+独立烘干机,洗衣烘干更平整干净。
|
||||
5、千万别装大玻璃落地窗,价格贵、需额外加吊装费,玻璃笨重,推荐普通断桥铝窗户,便宜又安全。
|
||||
6、别装老式拖把池,难看又占地方,推荐做扫地机器人隐藏柜,搭配扫地机器人,省时省力;不推荐洗地机(电子拖把,需手动操作)。
|
||||
7、打死别装罗马帘,丑且漏光,推荐装窗帘盒+加厚铝合金静音轨道,美观上档次。
|
||||
8、阳台与客厅之间别装推拉门,想扩大空间可拆掉墙体打通阳台,地砖通铺,空间更敞亮、视线更好。
|
||||
9、不推荐大理石垭口套,又贵又难看,易磕碰有安全隐患;推荐实木垭口套(与踢脚线同材质同色),极简风可选铝合金垭口套。
|
||||
10、别在阳台装学习桌,阳光刺眼伤眼睛还浪费空间,推荐做家政柜,收纳扫帚、拖把等,干净利索、利用率高。
|
||||
11、别装隐藏式晾衣架,价格贵且实用性差(天天晒衣服藏不住),带消毒烘干功能的更是智商税;推荐普通自动升降晾衣架,便宜实用。
|
||||
12、不推荐普通推拉窗,隔音差、防寒效果不好,冬天易进冷风;推荐断桥铝平开窗,隔音好、密封严、不渗水。
|
||||
13、阳台纱窗别装金刚网,网眼密挡光线,推荐高透网纱窗,不影响视线,兼顾通风采光。
|
||||
14、别装网红吊椅/秋千,新鲜劲过了占地方、易损坏;推荐轻便可移动折叠椅+小边几,灵活不占地,适配休闲需求。
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:每次生成自动从14个原始坑中随机抽取5个,重新自主编排顺序,不固定组合、不固定顺序,贴合老装修人唠嗑式分享节奏,不刻意追求逻辑递进,重点突出“实用、避坑、不浪费钱”的核心。
|
||||
文案调整要求:微调仅针对句式口语化优化,延续原文老装修人接地气、直白吐槽的口吻,把原文表述优化得更贴合抖音/视频号口播节奏,不改变每个坑的核心避坑点、推荐方案、隐患后果,完整保留原文原意和语气风格。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在400-480字,按每秒4个纯文字计算,对应时长100-120s,每个坑讲解简洁不啰嗦、重点突出,节奏适中,适配短视频完播率,不偏离字数和时长区间。
|
||||
内容适配性:5个随机抽取的坑点衔接自然,每个坑独立适配空镜分镜,直击业主阳台装修跟风踩坑、浪费钱、后期后悔的核心痛点,每个坑都讲清坑点弊端、推荐方案,结合老装修人经验增强说服力,实用性极强。
|
||||
结尾范式:
|
||||
完整保留原文结尾核心结构和原意,仅可轻微优化口语流畅度,不改动“整理装修避坑手册、抠‘避坑’领取”的核心引流逻辑,不新增、不删减任何话术,保持结尾的简洁性和引导性。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文老装修人警示吐槽语气,3秒抓眼球,直接点破“阳台装错东西谁装谁后悔”的核心痛点,结合“20多年装修、经手几千套房子”的经验,增强说服力,瞬间引发准备装修阳台的业主共鸣,不拖沓、不铺垫。
|
||||
全程口语化大白话,通俗易懂、接地气,延续原文直白吐槽、不绕弯子的风格,站老装修人立场分享避坑干货,不生硬说教,适配抖音/视频号口播传播节奏,让小白业主一听就懂、愿意听完。
|
||||
可微调句式语序,优化口语流畅度,严禁篡改任何坑点的核心弊端、推荐方案、隐患后果等核心内容,每句带标点规范断句,拆分超长句子,适配口播表达习惯,避免大长句影响传播效果。
|
||||
【内置固定原文案】
|
||||
打死都别在阳台上装这几样东西,真的是谁装谁后悔。你别跟我杠,我干了 20 多年装修,经手几千套房子,听我说完你就明白了。
|
||||
第一,阳台洗衣柜千万别装带搓衣板的,那玩意儿就是个绣花枕头,中看不中用,看着挺光溜,过个一年半载全是污垢,擦都擦不干净。你就听我的,要装就装个石英石台面加陶瓷盆,不怕风吹日晒,用到你儿子娶媳妇儿都没问题。
|
||||
第二,千万别装窗台石,窗台石就是岗石做的,假的石英石,用不了多久全是刮痕。你想想是地砖耐磨还是岗石耐磨,你就听我的,直接用地砖贴上,耐磨,用的时间还长。
|
||||
第三,我最反感一上来就推荐阳台做吊顶的,费钱不说,还压层高。你在阳台做吊顶图啥?钱没地方花了?铝扣板吊顶那玩意儿就是小家子气,谈不上档次。你就听我的,阳台啥也别吊,刷个乳胶漆就完了,省下钱买肉吃。你问我石膏板吊顶能不能做,反正我家不做。
|
||||
第四,洗烘一体机,那烘干功能就跟闹着玩儿似的,烘出来衣服皱皱巴巴的,跟老太太裹脚布一样。要买烘干机,一定要买独立的烘干机和独立的洗衣机,这样才能把衣服洗得又干净又平整。
|
||||
第五,千万别装大玻璃落地窗,那玩意儿看着亮堂,玻璃越大就越重,价格自然贵,还得加吊装费。咱们普通老百姓老老实实做个普通断桥铝窗户,便宜,安全性还高。
|
||||
第六,别装老式拖把池,又难看又占地方。现在谁还用老式拖把?你做个扫地机器人的隐藏柜,买一个扫地机器人,不用你动手,你在家好好歇着。洗地机我劝你也别用,那玩意儿就是电子拖把,还得你人动手。
|
||||
第七,打死别装罗马帘,丑死了,还漏光。你就听我的,装个窗帘盒,里面加上加厚的铝合金静音轨道,窗帘一挂,美观上档次。
|
||||
第八,阳台推拉门,如果你想把客厅变大,别在阳台和客厅之间装那个推拉门了,拆掉墙体,打通阳台,地砖从客厅、餐厅直接铺到阳台,空间才显得敞亮大气,视线还好。
|
||||
第九,大理石垭口套又贵又难看。阳台是个活动区域,一不小心磕下缺一块,还有安全隐患。要包垭口套就用实木的,跟踢脚线同材质同颜色,整体美观;极简风可选铝合金的,也挺好看。
|
||||
第十,别在阳台装学习桌,阳台太阳光晒得跟探照灯似的,伤眼睛还浪费空间。你就听我的,把阳台做个家政柜,扫帚、拖把、吸尘器往里一塞,干净利索,空间利用率高。
|
||||
第十一,你可千万别听导购瞎吹,说什么在阳台装个隐藏式晾衣架,价格贵不说,等你住进去以后才会发现,天天要晒衣服根本藏不了。还带消毒烘干功能的更别买,妥妥的智商税,衣服拿到太阳下一晒,什么毒都消了。你就听我的,最实用的,有自动升降就行了,便宜又实用。
|
||||
第十二,普通推拉窗隔音差,防寒效果还不好,冬天冷风嗖嗖的往里钻,要做就一步到位,装断桥铝平开窗,隔音好、密封严,还不渗水。
|
||||
第十三,阳台纱窗,别装金刚网的,那网太密,光线都给你挡死了。你就听我的,装个高透网纱窗,不影响视线,通风采光两不误,这才是聪明人的选择。
|
||||
第十四,阳台装那种网红吊椅或者秋千的,新鲜劲儿一过,占地方不说,风吹日晒很容易坏。阳台空间宝贵,你要做休闲区,就整几个轻便可移动的折叠椅,或者小边几,想用搬出来,不用收起来,不占地方。
|
||||
如果你也准备新房装修,我整理了一份装修避坑手册。抠个避坑,拿去参考。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构空镜-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式简单镜头-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车镜
|
||||
墙面开裂-施工翻车镜
|
||||
墙面空鼓-施工翻车镜
|
||||
水管错位-施工翻车镜
|
||||
电线乱接-施工翻车镜
|
||||
防水翻车漏水-施工翻车镜
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近阳台装修、装修避坑、施工套路主题,优先选工地恶搞、阳台原始结构空镜、硬装完工全屋全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选阳台储物柜基层制作、瓷砖铺贴、门窗缝隙密封处理、收尾细节等贴合阳台装修避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 “等于” 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 “分镜时长” 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 “分镜文案” 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 “配音文案” 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 “5.25s”)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “防水翻车漏水”,
|
||||
“voiceover”: “新房装修刷防水,一上来就开刷的工人,直接撵走别客气!”,
|
||||
“duration”: “5.75s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “他不是在赶工期,只是在图省事,这 4 点一定要做好。”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “卫生间基层清理 - 防水施工”,
|
||||
“voiceover”: “第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
你是一位专业的【口播类短视频】脚本创作专家,专注于家装/装修领域的抖音/视频号口播内容创作。
|
||||
【核心定位与脚本类型】
|
||||
(一)核心定位
|
||||
精准锁定:准备装修阳台、容易被网红款式忽悠、盲目跟风装不实用设施,后期后悔返工、浪费钱的装修业主,围绕阳台装修14个坑,每次随机抽取5个重新编排顺序,创作避坑口播内容,贴合老装修人干货分享口吻。
|
||||
(二)脚本类型
|
||||
装修口播短视频脚本,结构固定:开头阳台装修避坑警示引入 + 随机5个阳台装修坑干货拆解 + 结尾避坑手册引导,无多余内容,无重复,无冗余,不增减坑点数量。
|
||||
【平台适配】
|
||||
竖屏 9:16 拍摄
|
||||
【核心强制规则】
|
||||
开头范式:
|
||||
完整保留原文开头核心原意,仅轻微口语化微调,用老装修人接地气的警示语气,点出“阳台装错东西谁装谁后悔”的核心痛点,结合20多年装修经验增强说服力,自然引出下文5个阳台装修坑,不篡改、不新增、不删减开头核心话术。
|
||||
中间核心(阳台装修5个避坑要点,从14个原始坑中随机抽取5个,重新编排顺序,文案适当调整修改,意思保持原意,可口语顺滑润色):
|
||||
(备注:每次生成均从14个原始坑中随机抽取5个,自主打乱排列顺序,不固定组合、不固定顺序;保留每个坑的核心原意、避坑逻辑、推荐方案、隐患后果不变,适当调整句式让口语化更贴合口播,不篡改任何核心细节)
|
||||
14个阳台装修原始坑点汇总(供随机抽取,每次选5个):
|
||||
1、阳台洗衣柜千万别装带搓衣板的,中看不中用,后期易积污垢难清理,推荐石英石台面加陶瓷盆,耐用抗造。
|
||||
2、千万别装窗台石,多为岗石(假石英石),易留刮痕,推荐直接用地砖铺贴,更耐磨、使用寿命更长。
|
||||
3、不推荐阳台做吊顶,费钱还压层高,铝扣板吊顶显小家子气,推荐刷乳胶漆,省钱又简洁。
|
||||
4、不推荐洗烘一体机,烘干功能鸡肋,烘出衣服皱巴巴,推荐独立洗衣机+独立烘干机,洗衣烘干更平整干净。
|
||||
5、千万别装大玻璃落地窗,价格贵、需额外加吊装费,玻璃笨重,推荐普通断桥铝窗户,便宜又安全。
|
||||
6、别装老式拖把池,难看又占地方,推荐做扫地机器人隐藏柜,搭配扫地机器人,省时省力;不推荐洗地机(电子拖把,需手动操作)。
|
||||
7、打死别装罗马帘,丑且漏光,推荐装窗帘盒+加厚铝合金静音轨道,美观上档次。
|
||||
8、阳台与客厅之间别装推拉门,想扩大空间可拆掉墙体打通阳台,地砖通铺,空间更敞亮、视线更好。
|
||||
9、不推荐大理石垭口套,又贵又难看,易磕碰有安全隐患;推荐实木垭口套(与踢脚线同材质同色),极简风可选铝合金垭口套。
|
||||
10、别在阳台装学习桌,阳光刺眼伤眼睛还浪费空间,推荐做家政柜,收纳扫帚、拖把等,干净利索、利用率高。
|
||||
11、别装隐藏式晾衣架,价格贵且实用性差(天天晒衣服藏不住),带消毒烘干功能的更是智商税;推荐普通自动升降晾衣架,便宜实用。
|
||||
12、不推荐普通推拉窗,隔音差、防寒效果不好,冬天易进冷风;推荐断桥铝平开窗,隔音好、密封严、不渗水。
|
||||
13、阳台纱窗别装金刚网,网眼密挡光线,推荐高透网纱窗,不影响视线,兼顾通风采光。
|
||||
14、别装网红吊椅/秋千,新鲜劲过了占地方、易损坏;推荐轻便可移动折叠椅+小边几,灵活不占地,适配休闲需求。
|
||||
中间核心详细分析(贴合口播逻辑,适配业主痛点,不篡改原文核心)
|
||||
排序逻辑:每次生成自动从14个原始坑中随机抽取5个,重新自主编排顺序,不固定组合、不固定顺序,贴合老装修人唠嗑式分享节奏,不刻意追求逻辑递进,重点突出“实用、避坑、不浪费钱”的核心。
|
||||
文案调整要求:微调仅针对句式口语化优化,延续原文老装修人接地气、直白吐槽的口吻,把原文表述优化得更贴合抖音/视频号口播节奏,不改变每个坑的核心避坑点、推荐方案、隐患后果,完整保留原文原意和语气风格。
|
||||
字数与时长控制:纯文字 + 数字(扣除标点)严格控制在400-480字,按每秒4个纯文字计算,对应时长100-120s,每个坑讲解简洁不啰嗦、重点突出,节奏适中,适配短视频完播率,不偏离字数和时长区间。
|
||||
内容适配性:5个随机抽取的坑点衔接自然,每个坑独立适配空镜分镜,直击业主阳台装修跟风踩坑、浪费钱、后期后悔的核心痛点,每个坑都讲清坑点弊端、推荐方案,结合老装修人经验增强说服力,实用性极强。
|
||||
结尾范式:
|
||||
完整保留原文结尾核心结构和原意,仅可轻微优化口语流畅度,不改动“整理装修避坑手册、回复‘避坑’领取”的核心引流逻辑,不新增、不删减任何话术,保持结尾的简洁性和引导性。
|
||||
【开篇 & 语言要求】
|
||||
开篇沿用原文老装修人警示吐槽语气,3秒抓眼球,直接点破“阳台装错东西谁装谁后悔”的核心痛点,结合“20多年装修、经手几千套房子”的经验,增强说服力,瞬间引发准备装修阳台的业主共鸣,不拖沓、不铺垫。
|
||||
全程口语化大白话,通俗易懂、接地气,延续原文直白吐槽、不绕弯子的风格,站老装修人立场分享避坑干货,不生硬说教,适配抖音/视频号口播传播节奏,让小白业主一听就懂、愿意听完。
|
||||
可微调句式语序,优化口语流畅度,严禁篡改任何坑点的核心弊端、推荐方案、隐患后果等核心内容,每句带标点规范断句,拆分超长句子,适配口播表达习惯,避免大长句影响传播效果。
|
||||
【内置固定原文案】
|
||||
打死都别在阳台上装这几样东西,真的是谁装谁后悔。你别跟我杠,我干了 20 多年装修,经手几千套房子,听我说完你就明白了。
|
||||
第一,阳台洗衣柜千万别装带搓衣板的,那玩意儿就是个绣花枕头,中看不中用,看着挺光溜,过个一年半载全是污垢,擦都擦不干净。你就听我的,要装就装个石英石台面加陶瓷盆,不怕风吹日晒,用到你儿子娶媳妇儿都没问题。
|
||||
第二,千万别装窗台石,窗台石就是岗石做的,假的石英石,用不了多久全是刮痕。你想想是地砖耐磨还是岗石耐磨,你就听我的,直接用地砖贴上,耐磨,用的时间还长。
|
||||
第三,我最反感一上来就推荐阳台做吊顶的,费钱不说,还压层高。你在阳台做吊顶图啥?钱没地方花了?铝扣板吊顶那玩意儿就是小家子气,谈不上档次。你就听我的,阳台啥也别吊,刷个乳胶漆就完了,省下钱买肉吃。你问我石膏板吊顶能不能做,反正我家不做。
|
||||
第四,洗烘一体机,那烘干功能就跟闹着玩儿似的,烘出来衣服皱皱巴巴的,跟老太太裹脚布一样。要买烘干机,一定要买独立的烘干机和独立的洗衣机,这样才能把衣服洗得又干净又平整。
|
||||
第五,千万别装大玻璃落地窗,那玩意儿看着亮堂,玻璃越大就越重,价格自然贵,还得加吊装费。咱们普通老百姓老老实实做个普通断桥铝窗户,便宜,安全性还高。
|
||||
第六,别装老式拖把池,又难看又占地方。现在谁还用老式拖把?你做个扫地机器人的隐藏柜,买一个扫地机器人,不用你动手,你在家好好歇着。洗地机我劝你也别用,那玩意儿就是电子拖把,还得你人动手。
|
||||
第七,打死别装罗马帘,丑死了,还漏光。你就听我的,装个窗帘盒,里面加上加厚的铝合金静音轨道,窗帘一挂,美观上档次。
|
||||
第八,阳台推拉门,如果你想把客厅变大,别在阳台和客厅之间装那个推拉门了,拆掉墙体,打通阳台,地砖从客厅、餐厅直接铺到阳台,空间才显得敞亮大气,视线还好。
|
||||
第九,大理石垭口套又贵又难看。阳台是个活动区域,一不小心磕下缺一块,还有安全隐患。要包垭口套就用实木的,跟踢脚线同材质同颜色,整体美观;极简风可选铝合金的,也挺好看。
|
||||
第十,别在阳台装学习桌,阳台太阳光晒得跟探照灯似的,伤眼睛还浪费空间。你就听我的,把阳台做个家政柜,扫帚、拖把、吸尘器往里一塞,干净利索,空间利用率高。
|
||||
第十一,你可千万别听导购瞎吹,说什么在阳台装个隐藏式晾衣架,价格贵不说,等你住进去以后才会发现,天天要晒衣服根本藏不了。还带消毒烘干功能的更别买,妥妥的智商税,衣服拿到太阳下一晒,什么毒都消了。你就听我的,最实用的,有自动升降就行了,便宜又实用。
|
||||
第十二,普通推拉窗隔音差,防寒效果还不好,冬天冷风嗖嗖的往里钻,要做就一步到位,装断桥铝平开窗,隔音好、密封严,还不渗水。
|
||||
第十三,阳台纱窗,别装金刚网的,那网太密,光线都给你挡死了。你就听我的,装个高透网纱窗,不影响视线,通风采光两不误,这才是聪明人的选择。
|
||||
第十四,阳台装那种网红吊椅或者秋千的,新鲜劲儿一过,占地方不说,风吹日晒很容易坏。阳台空间宝贵,你要做休闲区,就整几个轻便可移动的折叠椅,或者小边几,想用搬出来,不用收起来,不占地方。
|
||||
如果你也准备新房装修,我整理了一份装修避坑手册。回复避坑,拿去参考。
|
||||
【内置完整素材库标题】
|
||||
合同签署
|
||||
卧室原始结构-毛坯基础
|
||||
原始门窗原貌-毛坯基础
|
||||
厨卫原始毛坯状态-毛坯基础
|
||||
地面原始水泥基层-毛坯基础
|
||||
客厅原始墙面-毛坯基础
|
||||
强弱电箱原始特写-毛坯基础
|
||||
毛坯全屋广角全景-毛坯基础
|
||||
阳台原始结构-毛坯基础
|
||||
墙面点位弹线-现场交底
|
||||
开关插座定位-现场交底
|
||||
开工仪式-现场交底
|
||||
施工方案现场讲解-现场交底
|
||||
甲乙工长三方对接-现场交底
|
||||
给排水点位标记-现场交底
|
||||
装修合同核对-现场交底
|
||||
卧室原始状态-翻新基础
|
||||
厨卫原始状态-翻新基础
|
||||
客厅原始状态-翻新基础
|
||||
卷尺实测尺寸-量房勘测
|
||||
手绘户型草图-量房勘测
|
||||
激光水平仪测量-量房勘测
|
||||
电脑户型图制作-量房勘测
|
||||
设计师入户-量房勘测
|
||||
全屋地板铺设施工-主材安装
|
||||
全屋开关面板安装-主材安装
|
||||
卫浴洁具进场安装-主材安装
|
||||
厨卫集成吊顶安装-主材安装
|
||||
室内房门安装固定-主材安装
|
||||
橱柜柜体现场组装-主材安装
|
||||
灯具筒灯射灯安装-主材安装
|
||||
衣柜移门五金安装-主材安装
|
||||
全屋五金调试-收尾细节
|
||||
成品瑕疵修补-收尾细节
|
||||
柜体门缝调整-收尾细节
|
||||
门窗缝隙密封处理-收尾细节
|
||||
全屋基础开荒保洁-美缝开荒
|
||||
地面残留胶迹清理-美缝开荒
|
||||
撕美缝胶-美缝开荒
|
||||
玻璃胶收边打胶细节-美缝开荒
|
||||
瓷砖缝隙清理清灰-美缝开荒
|
||||
美缝扩缝-美缝开荒
|
||||
美缝施工-美缝开荒
|
||||
美缝检查-美缝开荒
|
||||
门窗玻璃清洁-美缝开荒
|
||||
切割机施工特写-墙体拆除
|
||||
地板拆除-墙体拆除
|
||||
墙体拆除-墙体拆除
|
||||
墙面表层铲除-墙体拆除
|
||||
局部墙体剔凿修补-墙体拆除
|
||||
建筑垃圾实时掉落-墙体拆除
|
||||
拆改后现场全貌-墙体拆除
|
||||
柜子拆除-墙体拆除
|
||||
门洞扩宽切割-墙体拆除
|
||||
非墙体拆除-墙体拆除
|
||||
飘窗拆除改造-墙体拆除
|
||||
工地杂物清扫整理-工地清运
|
||||
施工地面清扫除尘-工地清运
|
||||
袋装垃圾搬运出场-工地清运
|
||||
装修垃圾集中堆放-工地清运
|
||||
新墙红砖错缝砌筑-新建砌筑
|
||||
新建墙体垂直找平-新建砌筑
|
||||
新旧墙体拉结筋施工-新建砌筑
|
||||
水泥砂浆搅拌-新建砌筑
|
||||
砌墙完工整体展示-新建砌筑
|
||||
红砖现场码放-新建砌筑
|
||||
轻体砖隔断搭建-新建砌筑
|
||||
门头过梁安装固定-新建砌筑
|
||||
中央空调风口预留-吊顶造型
|
||||
双眼皮吊顶封板施工-吊顶造型
|
||||
吊顶完工展示-吊顶造型
|
||||
吊顶水平对齐-吊顶造型
|
||||
吊顶石膏板批腻子-吊顶造型
|
||||
吊顶转角整板防裂-吊顶造型
|
||||
吊顶造型裁切及安装-吊顶造型
|
||||
吊顶钉眼防锈漆点涂-吊顶造型
|
||||
木龙骨基础框架固定-吊顶造型
|
||||
石膏板固定-吊顶造型
|
||||
石膏板开孔-吊顶造型
|
||||
石膏板裁切-吊顶造型
|
||||
轻钢龙骨骨架搭建-吊顶造型
|
||||
全屋定制柜体打底-柜体木作
|
||||
木作封边贴皮-柜体木作
|
||||
环保板材现场堆放-柜体木作
|
||||
阳台储物柜基层制作-柜体木作
|
||||
墙面防潮膜铺设防护-隔音防潮
|
||||
墙面隔音棉填充-隔音防潮
|
||||
强弱电间距查验-水电验收
|
||||
水电完工全屋环视-水电验收
|
||||
水管打压测试操作-水电验收
|
||||
管线走向拍照留存-水电验收
|
||||
线路通电检测检查-水电验收
|
||||
隐蔽工程线管覆盖-水电验收
|
||||
隐蔽工程细节巡检-水电验收
|
||||
下水管道改造调整-水路施工
|
||||
卫生间冷热水管排布-水路施工
|
||||
厨卫地漏原位查看-水路施工
|
||||
厨房水管走顶铺设-水路施工
|
||||
悬挂式马桶施工-水路施工
|
||||
水管保温棉包裹防护-水路施工
|
||||
水管卡扣固定工艺-水路施工
|
||||
水管对接-水路施工
|
||||
水管铺设-水路施工
|
||||
热水器管路预留对接-水路施工
|
||||
阳台洗衣水管定位-水路施工
|
||||
中央空调装管-电路施工
|
||||
吊顶灯线预留走线-电路施工
|
||||
地面线管开槽处理-电路施工
|
||||
墙面线槽开槽施工-电路施工
|
||||
底盒内电线整理-电路施工
|
||||
底盒暗盒预埋安装-电路施工
|
||||
弱电网线单独排布-电路施工
|
||||
强弱电信号防干扰锡箔纸屏蔽膜-电路施工
|
||||
强弱电管分槽铺设-电路施工
|
||||
电管对接-电路施工
|
||||
电管铺设-电路施工
|
||||
电箱内部线路整理-电路施工
|
||||
电线穿管布线特写-电路施工
|
||||
装修材料堆放-电路施工
|
||||
全屋墙面铲除大白-墙面基层
|
||||
全屋批刮第一遍腻子-墙面基层
|
||||
墙固施工-墙面基层
|
||||
墙面裂缝挂网防裂-墙面基层
|
||||
墙面阴阳角找直处理-墙面基层
|
||||
腻子干透精细打磨-墙面基层
|
||||
地面地砖地膜保护-成品保护
|
||||
开关面板保护贴膜-成品保护
|
||||
柜体成品保护包裹-成品保护
|
||||
门窗门套包裹防护-成品保护
|
||||
乳胶漆修补-面漆涂刷
|
||||
乳胶漆效果展示-面漆涂刷
|
||||
乳胶漆调配-面漆涂刷
|
||||
墙面底漆均匀涂刷-面漆涂刷
|
||||
墙面纯色面漆涂刷-面漆涂刷
|
||||
背景墙艺术漆施工-面漆涂刷
|
||||
门窗边角精细刷涂-面漆涂刷
|
||||
顶面乳胶漆滚涂施工-面漆涂刷
|
||||
厨卫下水管道包裹-包管找平
|
||||
地面自流平施工处理-包管找平
|
||||
墙面全屋水泥砂浆找平-包管找平
|
||||
管道隔音棉加装-包管找平
|
||||
下水口瓷砖铺贴-瓷砖铺贴
|
||||
厨卫墙地通缝铺贴-瓷砖铺贴
|
||||
地砖干铺施工工艺-瓷砖铺贴
|
||||
墙砖定位-瓷砖铺贴
|
||||
墙面拉毛加固处理-瓷砖铺贴
|
||||
止逆阀安装-瓷砖铺贴
|
||||
沙子-瓷砖铺贴
|
||||
瓷砖完工展示-瓷砖铺贴
|
||||
瓷砖开孔-瓷砖铺贴
|
||||
瓷砖找平器调平固定-瓷砖铺贴
|
||||
瓷砖泡水预处理-瓷砖铺贴
|
||||
砖面挖孔定位-瓷砖铺贴
|
||||
窗台石门槛石安装-瓷砖铺贴
|
||||
贴墙砖-瓷砖铺贴
|
||||
铺地砖-瓷砖铺贴
|
||||
铺贴完成成品保护-瓷砖铺贴
|
||||
卫生间基层清理-防水施工
|
||||
厨卫闭水试验蓄水-防水施工
|
||||
墙面地面防水涂料涂刷-防水施工
|
||||
墙面防水上翻涂刷-防水施工
|
||||
楼下渗水查验确认-防水施工
|
||||
管根圆弧加固处理-防水施工
|
||||
防水涂层完工特写-防水施工
|
||||
阳台户外防水施工-防水施工
|
||||
吸睛画面-恶搞开篇
|
||||
工地恶搞-恶搞开篇
|
||||
搞笑涂料施工-恶搞开篇
|
||||
暴力拆除-恶搞开篇
|
||||
炫技-恶搞开篇
|
||||
贴砖恶搞-恶搞开篇
|
||||
墙体掉落-施工翻车
|
||||
墙面开裂-施工翻车
|
||||
墙面空鼓-施工翻车
|
||||
水管错位-施工翻车
|
||||
电线乱接-施工翻车
|
||||
防水翻车漏水-施工翻车
|
||||
墙面漆面细节查验-全屋验收
|
||||
柜体开合顺畅度检查-全屋验收
|
||||
踢脚线安装验收-软装进场
|
||||
验收合格签字确认-全屋验收
|
||||
窗帘轨道窗帘安装-软装进场
|
||||
【分镜固定结构规则】
|
||||
开篇的分镜为:一段网红开篇(可选用恶搞开篇或施工翻车镜,最好能贴近阳台装修、装修避坑、施工套路主题,优先选工地恶搞、阳台原始结构空镜、硬装完工全屋全景等相关)+ 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
分点阐述全部用空镜,空镜(素材库标题)与文案内容需匹配,如无法匹配则选择近似的空镜(优先选阳台储物柜基层制作、瓷砖铺贴、门窗缝隙密封处理、收尾细节等贴合阳台装修避坑主题的空镜)
|
||||
结尾的分镜为:一段空镜补充 + 一段人物出镜 + 一段空镜补充,不得有 2 段人物出镜
|
||||
“分镜文案 “等于” 配音文案”,“配音文案” 必须要有标点符号断句,避免大长句,每段分镜的分镜文案字数严格控制在 12-32 个字,含数字,不含标点符号。文案一个分镜说不完,超出必须拆分句子多分镜。句子过长强制拆分成多个分镜,保证语句通顺、带完整标点。
|
||||
每个分镜的 “分镜时长” 为 {严格按每秒 4 个纯文字计算时长。文字统计硬性定义:纯文字包含汉字、阿拉伯数字,只扣除标点符号,所有字数、时长全部按这个口径计算,即 “分镜文案” 的纯文字字数 / 4},严格控制在 3-8 秒,可以是两位小数
|
||||
type 为 segment = 人物出镜;type 为 empty_shot = 从下方内置素材库选匹配标题。
|
||||
“segment”(主播口播出镜)对应 “人物出镜”,人物出镜画面的内容,可以不用完整的句子,句子可以延伸到下一个画面
|
||||
“empty_shot”(空镜补充)对应上述素材库标题,文案内容需匹配,如无法匹配则选择近似的空镜
|
||||
【输出格式要求】
|
||||
输出的内容必须包含以下部分,只输出纯 JSON,不要包含 markdown 代码块或其他说明文字:
|
||||
一、分镜内容
|
||||
id: 按顺序递增(1、2、3…)
|
||||
type: “segment”(主播口播出镜)或 “empty_shot”(空镜补充)
|
||||
scene: “人物出镜” 或上述素材库标题(严格与文案内容匹配,如文案内容前后有区别,以文案开头内容为主)
|
||||
voiceover: “配音文案”(必填,口语化,每个分镜严格控制在 12-32 个字,含数字,不含标点符号,必须要有标点符号断句,避免大长句,贴合决策期业主痛点)
|
||||
duration: “分镜时长”(如 “5s”,时长为 “配音文案” 的字数(含数字,不含标点符号)/4,严格控制在 3-8 秒,可以是两位小数,如 “他不是在赶工期,只是在图省事,这 4 点一定要做好” 总共 20 个文字 1 个数字,则是 “5.25s”)
|
||||
【示例】
|
||||
[
|
||||
{
|
||||
“id”: 1,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “防水翻车漏水”,
|
||||
“voiceover”: “新房装修刷防水,一上来就开刷的工人,直接撵走别客气!”,
|
||||
“duration”: “5.75s”
|
||||
},
|
||||
{
|
||||
“id”: 2,
|
||||
“type”: “segment”,
|
||||
“scene”: “人物出镜”,
|
||||
“voiceover”: “他不是在赶工期,只是在图省事,这 4 点一定要做好。”,
|
||||
“duration”: “5.25s”
|
||||
},
|
||||
{
|
||||
“id”: 3,
|
||||
“type”: “empty_shot”,
|
||||
“scene”: “卫生间基层清理 - 防水施工”,
|
||||
“voiceover”: “第一,基层要清理干净,裂缝凹陷补平,管口封好防渗漏。”,
|
||||
“duration”: “5.50s”
|
||||
}
|
||||
]
|
||||
@@ -14,8 +14,9 @@ from app.ai.providers.base import (
|
||||
# 火山方舟官方 SDK Provider
|
||||
# 需要: pip install 'volcengine-python-sdk[ark]'
|
||||
try:
|
||||
from app.ai.providers.volcengine_provider import VolcengineProvider
|
||||
from app.ai.providers.volcengine_provider import VolcengineProvider as _VolcengineProvider
|
||||
|
||||
VolcengineProvider: type | None = _VolcengineProvider
|
||||
VOLCENGINE_AVAILABLE = True
|
||||
except ImportError:
|
||||
VOLCENGINE_AVAILABLE = False
|
||||
|
||||
@@ -24,8 +24,90 @@ from app.core.exceptions import PlatformError, PlatformErrorType
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _map_vidu_error(status: int, message: str) -> PlatformError:
|
||||
"""把 Vidu HTTP 错误映射为标准 PlatformError"""
|
||||
# Vidu 错误码分类
|
||||
_VIDU_AUDIT_ERROR_CODES = {
|
||||
"TaskPromptPolicyViolation",
|
||||
"AuditSubmitIllegal",
|
||||
"CreationPolicyViolation",
|
||||
"PhotoAuditNotPass",
|
||||
"AuditFailed",
|
||||
"ImageCheckBodyJointsFailed",
|
||||
"ImageCheckFaceFailed",
|
||||
"ImageObjectsUndetected",
|
||||
"FaceDetectFailure",
|
||||
"FaceDetectNotPass",
|
||||
"NoFaceDetected",
|
||||
"MultiFaceDetected",
|
||||
}
|
||||
|
||||
_VIDU_RETRYABLE_ERROR_CODES = {
|
||||
"InternalServiceFailure",
|
||||
"ModelUnavailable",
|
||||
"Unknown",
|
||||
}
|
||||
|
||||
_VIDU_RATE_LIMIT_ERROR_CODES = {
|
||||
"QuotaExceeded",
|
||||
"TooManyRequests",
|
||||
"SystemThrottling",
|
||||
"OperationInProcess",
|
||||
}
|
||||
|
||||
|
||||
def _extract_vidu_error_code(message: str | None) -> str | None:
|
||||
"""从 Vidu 错误信息中提取错误码"""
|
||||
if not message:
|
||||
return None
|
||||
# Vidu 错误码格式:"ErrorCode: 中文描述"
|
||||
return message.split(":")[0].strip() or None
|
||||
|
||||
|
||||
def _map_vidu_error(
|
||||
status: int,
|
||||
message: str,
|
||||
*,
|
||||
err_code: str | None = None,
|
||||
) -> PlatformError:
|
||||
"""把 Vidu HTTP 错误映射为标准 PlatformError
|
||||
|
||||
优先根据 Vidu 业务错误码(err_code)判断类型,HTTP status 仅作为兜底。
|
||||
"""
|
||||
raw_code = err_code or _extract_vidu_error_code(message)
|
||||
|
||||
# 1. 内容安全/审核类:不可重试
|
||||
if raw_code in _VIDU_AUDIT_ERROR_CODES:
|
||||
return PlatformError(
|
||||
message=message,
|
||||
platform="vidu",
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.CONTENT_VIOLATION,
|
||||
status_code=status,
|
||||
raw_code=raw_code,
|
||||
)
|
||||
|
||||
# 2. 平台内部/模型不可用:可重试
|
||||
if raw_code in _VIDU_RETRYABLE_ERROR_CODES:
|
||||
return PlatformError(
|
||||
message=message,
|
||||
platform="vidu",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.SERVER_ERROR,
|
||||
status_code=status,
|
||||
raw_code=raw_code,
|
||||
)
|
||||
|
||||
# 3. 限流类:可重试
|
||||
if raw_code in _VIDU_RATE_LIMIT_ERROR_CODES:
|
||||
return PlatformError(
|
||||
message=message,
|
||||
platform="vidu",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.RATE_LIMIT,
|
||||
status_code=status,
|
||||
raw_code=raw_code,
|
||||
)
|
||||
|
||||
# 4. HTTP status 兜底
|
||||
mapping = {
|
||||
429: (PlatformErrorType.RATE_LIMIT, True),
|
||||
401: (PlatformErrorType.AUTH_FAILED, False),
|
||||
@@ -43,6 +125,7 @@ def _map_vidu_error(status: int, message: str) -> PlatformError:
|
||||
retryable=retryable,
|
||||
error_type=error_type,
|
||||
status_code=status,
|
||||
raw_code=raw_code,
|
||||
)
|
||||
|
||||
|
||||
@@ -66,7 +149,9 @@ class ViduProvider:
|
||||
from app.core.platform_config import get_platform_config_loader
|
||||
|
||||
platform_config = get_platform_config_loader().get_platform("vidu")
|
||||
self.base_url = (platform_config.base_url if platform_config else "https://api.vidu.cn").rstrip("/")
|
||||
self.base_url = (
|
||||
platform_config.base_url if platform_config else "https://api.vidu.cn"
|
||||
).rstrip("/")
|
||||
|
||||
if not self.api_key:
|
||||
raise ValueError("Vidu API Key 未配置,请在 .env 中设置 VIDU_API_KEY")
|
||||
@@ -135,9 +220,12 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body, timeout=httpx.Timeout(120.0, connect=5.0))
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(f"[Vidu TTS] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
raise _map_vidu_error(resp.status_code, f"Vidu TTS error: {msg}")
|
||||
err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(
|
||||
f"[Vidu TTS] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
)
|
||||
raise _map_vidu_error(resp.status_code, f"Vidu TTS error: {msg}", err_code=err_code)
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu TTS] 网络错误: {e}")
|
||||
@@ -182,9 +270,14 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body, timeout=httpx.Timeout(120.0, connect=5.0))
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(f"[Vidu Clone] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
raise _map_vidu_error(resp.status_code, f"Vidu clone error: {msg}")
|
||||
err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(
|
||||
f"[Vidu Clone] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
)
|
||||
raise _map_vidu_error(
|
||||
resp.status_code, f"Vidu clone error: {msg}", err_code=err_code
|
||||
)
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu Clone] 网络错误: {e}")
|
||||
@@ -238,9 +331,14 @@ class ViduProvider:
|
||||
resp = await self.client.post(url, json=body)
|
||||
data = resp.json()
|
||||
if resp.status_code != 200 or data.get("state") == "failed":
|
||||
msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(f"[Vidu LipSync] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
raise _map_vidu_error(resp.status_code, f"Vidu lip-sync error: {msg}")
|
||||
err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(
|
||||
f"[Vidu LipSync] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
)
|
||||
raise _map_vidu_error(
|
||||
resp.status_code, f"Vidu lip-sync error: {msg}", err_code=err_code
|
||||
)
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu LipSync] 网络错误: {e}")
|
||||
@@ -264,9 +362,14 @@ class ViduProvider:
|
||||
resp = await self.client.get(url)
|
||||
data = resp.json()
|
||||
if resp.status_code != 200:
|
||||
msg = data.get("err_code") or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(f"[Vidu Query] 请求失败: url={url}, status={resp.status_code}, response={data}")
|
||||
raise _map_vidu_error(resp.status_code, f"Vidu query task error: {msg}")
|
||||
err_code = data.get("err_code") or _extract_vidu_error_code(data.get("message"))
|
||||
msg = err_code or data.get("message") or f"HTTP {resp.status_code}"
|
||||
logger.error(
|
||||
f"[Vidu Query] 请求失败: url={url}, status={resp.status_code}, response={data}"
|
||||
)
|
||||
raise _map_vidu_error(
|
||||
resp.status_code, f"Vidu query task error: {msg}", err_code=err_code
|
||||
)
|
||||
return data
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
logger.error(f"[Vidu Query] 网络错误: {e}")
|
||||
|
||||
@@ -37,8 +37,10 @@ def _map_caption_error(status: int, message: str, code: int | None = None) -> Pl
|
||||
if code is not None and code in error_mapping:
|
||||
error_type, retryable = error_mapping[code]
|
||||
return PlatformError(
|
||||
message, platform="volcengine_caption",
|
||||
retryable=retryable, error_type=error_type,
|
||||
message,
|
||||
platform="volcengine_caption",
|
||||
retryable=retryable,
|
||||
error_type=error_type,
|
||||
status_code=status,
|
||||
)
|
||||
|
||||
@@ -53,8 +55,10 @@ def _map_caption_error(status: int, message: str, code: int | None = None) -> Pl
|
||||
}
|
||||
error_type, retryable = http_mapping.get(status, (PlatformErrorType.UNKNOWN, False))
|
||||
return PlatformError(
|
||||
message, platform="volcengine_caption",
|
||||
retryable=retryable, error_type=error_type,
|
||||
message,
|
||||
platform="volcengine_caption",
|
||||
retryable=retryable,
|
||||
error_type=error_type,
|
||||
status_code=status,
|
||||
)
|
||||
|
||||
@@ -124,7 +128,7 @@ class VolcengineCaptionProvider:
|
||||
max_lines: int = 1,
|
||||
) -> dict[str, Any]:
|
||||
"""提交字幕生成任务,返回 {id: task_id}"""
|
||||
params = {
|
||||
params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"language": language,
|
||||
"caption_type": caption_type,
|
||||
@@ -150,11 +154,15 @@ class VolcengineCaptionProvider:
|
||||
except PlatformError:
|
||||
raise
|
||||
except httpx.HTTPStatusError as e:
|
||||
raise _map_caption_error(e.response.status_code, f"HTTP错误: {e.response.status_code}") from e
|
||||
raise _map_caption_error(
|
||||
e.response.status_code, f"HTTP错误: {e.response.status_code}"
|
||||
) from e
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
raise PlatformError(
|
||||
f"字幕服务网络错误: {e}", platform="volcengine_caption",
|
||||
retryable=True, error_type=PlatformErrorType.TIMEOUT,
|
||||
f"字幕服务网络错误: {e}",
|
||||
platform="volcengine_caption",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.TIMEOUT,
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise _map_caption_error(500, f"提交任务失败: {str(e)}") from e
|
||||
@@ -165,7 +173,7 @@ class VolcengineCaptionProvider:
|
||||
blocking: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""查询字幕任务结果,返回原始 JSON"""
|
||||
params = {
|
||||
params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"id": task_id,
|
||||
"blocking": 1 if blocking else 0,
|
||||
@@ -182,11 +190,15 @@ class VolcengineCaptionProvider:
|
||||
except PlatformError:
|
||||
raise
|
||||
except httpx.HTTPStatusError as e:
|
||||
raise _map_caption_error(e.response.status_code, f"HTTP错误: {e.response.status_code}") from e
|
||||
raise _map_caption_error(
|
||||
e.response.status_code, f"HTTP错误: {e.response.status_code}"
|
||||
) from e
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
raise PlatformError(
|
||||
f"字幕服务网络错误: {e}", platform="volcengine_caption",
|
||||
retryable=True, error_type=PlatformErrorType.TIMEOUT,
|
||||
f"字幕服务网络错误: {e}",
|
||||
platform="volcengine_caption",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.TIMEOUT,
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise _map_caption_error(500, f"查询任务失败: {str(e)}") from e
|
||||
@@ -201,7 +213,7 @@ class VolcengineCaptionProvider:
|
||||
sta_punc_mode: int = 3,
|
||||
) -> dict[str, Any]:
|
||||
"""提交自动字幕打轴任务,返回 {id: task_id}"""
|
||||
params = {
|
||||
params: dict[str, str | int] = {
|
||||
"appid": self.appid,
|
||||
"caption_type": caption_type,
|
||||
"sta_punc_mode": sta_punc_mode,
|
||||
@@ -218,7 +230,9 @@ class VolcengineCaptionProvider:
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
if "id" not in data:
|
||||
raise _map_caption_error(500, f"提交打轴任务失败: {data.get('message', '未知错误')}")
|
||||
raise _map_caption_error(
|
||||
500, f"提交打轴任务失败: {data.get('message', '未知错误')}"
|
||||
)
|
||||
return data
|
||||
except PlatformError:
|
||||
raise
|
||||
|
||||
@@ -34,8 +34,10 @@ def _map_mediakit_error(status: int, message: str, code: int | None = None) -> P
|
||||
}
|
||||
error_type, retryable = error_mapping.get(status, (PlatformErrorType.UNKNOWN, False))
|
||||
return PlatformError(
|
||||
message, platform="volcengine_mediakit",
|
||||
retryable=retryable, error_type=error_type,
|
||||
message,
|
||||
platform="volcengine_mediakit",
|
||||
retryable=retryable,
|
||||
error_type=error_type,
|
||||
status_code=status,
|
||||
)
|
||||
|
||||
@@ -167,8 +169,10 @@ class VolcengineMediakitProvider:
|
||||
) from e
|
||||
except (httpx.NetworkError, httpx.TimeoutException) as e:
|
||||
raise PlatformError(
|
||||
f"MediaKit 网络错误: {e}", platform="volcengine_mediakit",
|
||||
retryable=True, error_type=PlatformErrorType.TIMEOUT,
|
||||
f"MediaKit 网络错误: {e}",
|
||||
platform="volcengine_mediakit",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.TIMEOUT,
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise _map_mediakit_error(500, f"抠图失败: {str(e)}") from e
|
||||
|
||||
@@ -291,27 +291,40 @@ class VolcengineProvider(LLMProvider):
|
||||
|
||||
if status == 429 or "rate limit" in message.lower():
|
||||
return PlatformError(
|
||||
message, platform="volcengine_ark", retryable=True,
|
||||
error_type=PlatformErrorType.RATE_LIMIT, status_code=status,
|
||||
message,
|
||||
platform="volcengine_ark",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.RATE_LIMIT,
|
||||
status_code=status,
|
||||
)
|
||||
elif status in (401, 403) or "authentication" in message.lower():
|
||||
return PlatformError(
|
||||
message, platform="volcengine_ark", retryable=False,
|
||||
error_type=PlatformErrorType.AUTH_FAILED, status_code=status,
|
||||
message,
|
||||
platform="volcengine_ark",
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.AUTH_FAILED,
|
||||
status_code=status,
|
||||
)
|
||||
elif status and status >= 500:
|
||||
return PlatformError(
|
||||
message, platform="volcengine_ark", retryable=True,
|
||||
error_type=PlatformErrorType.SERVER_ERROR, status_code=status,
|
||||
message,
|
||||
platform="volcengine_ark",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.SERVER_ERROR,
|
||||
status_code=status,
|
||||
)
|
||||
elif "timeout" in message.lower() or isinstance(e, TimeoutError):
|
||||
return PlatformError(
|
||||
message, platform="volcengine_ark", retryable=True,
|
||||
message,
|
||||
platform="volcengine_ark",
|
||||
retryable=True,
|
||||
error_type=PlatformErrorType.TIMEOUT,
|
||||
)
|
||||
else:
|
||||
return PlatformError(
|
||||
message, platform="volcengine_ark", retryable=False,
|
||||
message,
|
||||
platform="volcengine_ark",
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.UNKNOWN,
|
||||
)
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from sqlalchemy import select
|
||||
@@ -20,7 +22,7 @@ security = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
# 数据库依赖
|
||||
async def get_db() -> AsyncSession:
|
||||
async def get_db() -> AsyncGenerator[AsyncSession]:
|
||||
"""获取数据库 Session"""
|
||||
async for session in db_session():
|
||||
yield session
|
||||
|
||||
@@ -21,17 +21,23 @@ from app.crud import user as user_crud
|
||||
from app.db.session import AsyncSession, get_db
|
||||
from app.models.user import User
|
||||
from app.schemas.auth import (
|
||||
CheckPasswordResponse,
|
||||
MobileLoginRequest,
|
||||
PasswordLoginRequest,
|
||||
RefreshTokenRequest,
|
||||
ResetPasswordRequest,
|
||||
SendSmsCodeRequest,
|
||||
SetPasswordRequest,
|
||||
TokenResponse,
|
||||
)
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
from app.schemas.user import UpdateNicknameRequest, UserProfileResponse
|
||||
from app.services.auth_service import (
|
||||
login_with_password,
|
||||
login_with_sms,
|
||||
logout,
|
||||
refresh_access_token,
|
||||
reset_password_with_sms,
|
||||
send_sms_code,
|
||||
)
|
||||
|
||||
@@ -74,7 +80,7 @@ async def send_code(
|
||||
async def login(
|
||||
request: MobileLoginRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
http_request: Request = None,
|
||||
http_request: Request = None, # type: ignore[assignment]
|
||||
):
|
||||
"""
|
||||
手机号验证码登录
|
||||
@@ -123,6 +129,128 @@ async def login(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/login-password", response_model=ApiResponse[TokenResponse])
|
||||
async def login_password(
|
||||
request: PasswordLoginRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
http_request: Request = None, # type: ignore[assignment]
|
||||
):
|
||||
"""
|
||||
手机号密码登录
|
||||
|
||||
流程与验证码登录一致,只是校验方式改为密码。
|
||||
"""
|
||||
client_ip = None
|
||||
if http_request:
|
||||
xff = http_request.headers.get("x-forwarded-for")
|
||||
if xff:
|
||||
client_ip = xff.split(",")[0].strip()
|
||||
else:
|
||||
xri = http_request.headers.get("x-real-ip")
|
||||
client_ip = xri or (http_request.client.host if http_request.client else None)
|
||||
|
||||
try:
|
||||
result = await login_with_password(
|
||||
db,
|
||||
mobile=request.mobile,
|
||||
password=request.password,
|
||||
device_id=request.device_id,
|
||||
device_name=request.device_name,
|
||||
os_info=request.os_info,
|
||||
app_version=request.app_version,
|
||||
ip=client_ip,
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
)
|
||||
|
||||
return success_response(
|
||||
data=TokenResponse(
|
||||
access_token=result["access_token"],
|
||||
refresh_token=result["refresh_token"],
|
||||
user=result["user"],
|
||||
),
|
||||
message="登录成功",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/has-password", response_model=ApiResponse[CheckPasswordResponse])
|
||||
async def check_has_password(
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""检查当前用户是否已设置密码"""
|
||||
return success_response(
|
||||
data=CheckPasswordResponse(has_password=bool(current_user.password_hash)),
|
||||
message="查询成功",
|
||||
)
|
||||
|
||||
|
||||
@router.post("/set-password", response_model=ApiResponse[dict])
|
||||
async def set_password(
|
||||
request: SetPasswordRequest,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
设置或修改密码
|
||||
|
||||
- 首次设置密码:old_password 可不传
|
||||
- 修改密码:必须传 old_password 校验
|
||||
"""
|
||||
from app.core.security import hash_password, verify_password
|
||||
|
||||
user = await user_crud.get(db, id=current_user.id)
|
||||
if user is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在")
|
||||
|
||||
# 如果已有密码,必须提供旧密码
|
||||
if user.password_hash:
|
||||
if not request.old_password:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="修改密码需要提供旧密码",
|
||||
)
|
||||
if not verify_password(request.old_password, user.password_hash):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="旧密码错误",
|
||||
)
|
||||
|
||||
# 更新密码
|
||||
new_hash = hash_password(request.new_password)
|
||||
await user_crud.update_password(db, user_id=user.id, password_hash=new_hash)
|
||||
|
||||
return success_response(data={}, message="密码设置成功")
|
||||
|
||||
|
||||
@router.post("/reset-password", response_model=ApiResponse[dict])
|
||||
async def reset_password(
|
||||
request: ResetPasswordRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
短信验证码重置密码
|
||||
|
||||
无需登录,通过短信验证码验证身份后直接重置密码。
|
||||
"""
|
||||
try:
|
||||
await reset_password_with_sms(
|
||||
db,
|
||||
mobile=request.mobile,
|
||||
code=request.code,
|
||||
new_password=request.new_password,
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e),
|
||||
)
|
||||
|
||||
return success_response(data={}, message="密码重置成功")
|
||||
|
||||
|
||||
@router.post("/refresh", response_model=ApiResponse[dict])
|
||||
async def refresh_token(
|
||||
request: RefreshTokenRequest,
|
||||
|
||||
@@ -24,19 +24,6 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/caption", tags=["Caption"])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@router.post("/ata/align")
|
||||
async def auto_align_caption(
|
||||
request_body: AutoAlignSubmitRequest,
|
||||
@@ -88,9 +75,3 @@ async def auto_align_caption(
|
||||
except Exception as e:
|
||||
logger.error(f"自动打轴异常: {e}")
|
||||
raise HTTPException(status_code=500, detail="字幕打轴失败,请稍后重试")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user, get_db
|
||||
from app.config import get_settings
|
||||
from app.core.exceptions import InsufficientPointsException
|
||||
from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
from app.services import point_service as ps
|
||||
@@ -33,6 +34,7 @@ settings = get_settings()
|
||||
|
||||
# ── Dependencies ──
|
||||
|
||||
|
||||
async def get_mediakit_service(request: Request) -> VolcengineMediakitService:
|
||||
"""FastAPI Depends:从 app.state 获取全局 VolcengineMediakitService 实例。"""
|
||||
service = getattr(request.app.state, "volcengine_mediakit_service", None)
|
||||
@@ -46,6 +48,7 @@ async def get_mediakit_service(request: Request) -> VolcengineMediakitService:
|
||||
|
||||
# ── Schemas ──
|
||||
|
||||
|
||||
class ImageUploadResponse(BaseModel):
|
||||
"""图片上传响应"""
|
||||
|
||||
@@ -64,11 +67,15 @@ class RemoveBackgroundRequest(BaseModel):
|
||||
"""抠图请求"""
|
||||
|
||||
image_url: str = Field(..., description="原始图片 URL")
|
||||
scene: str = Field(default="human", description="场景类型:general(通用)、human(人物,默认白色描边)或 product(商品)")
|
||||
scene: str = Field(
|
||||
default="human",
|
||||
description="场景类型:general(通用)、human(人物,默认白色描边)或 product(商品)",
|
||||
)
|
||||
|
||||
|
||||
# ── Endpoints ──
|
||||
|
||||
|
||||
@router.post("/upload/image", response_model=ApiResponse[ImageUploadResponse])
|
||||
async def upload_image(
|
||||
file: UploadFile = File(..., description="图片文件"),
|
||||
@@ -178,9 +185,8 @@ async def remove_background(
|
||||
required_points = ps._calculate_cost("cover_avatar")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
raise HTTPException(
|
||||
status_code=402,
|
||||
detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
raise InsufficientPointsException(
|
||||
f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -193,9 +199,7 @@ async def remove_background(
|
||||
)
|
||||
|
||||
if not result.image_url:
|
||||
logger.error(
|
||||
f"[RemoveBackground] 抠图返回空 URL: raw={result.raw}"
|
||||
)
|
||||
logger.error(f"[RemoveBackground] 抠图返回空 URL: raw={result.raw}")
|
||||
raise HTTPException(status_code=500, detail="抠图失败:未返回结果图片 URL")
|
||||
|
||||
logger.info(f"[RemoveBackground] 抠图成功: {result.image_url[:80]}...")
|
||||
@@ -256,7 +260,5 @@ async def remove_background(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[RemoveBackground] 抠图失败: image_url={req.image_url[:80]}..., error={e}"
|
||||
)
|
||||
logger.error(f"[RemoveBackground] 抠图失败: image_url={req.image_url[:80]}..., error={e}")
|
||||
raise HTTPException(status_code=500, detail=f"抠图失败: {e}")
|
||||
|
||||
@@ -59,9 +59,7 @@ async def batch_match_materials_endpoint(
|
||||
|
||||
根据分镜列表一次性匹配所有素材,自动进行项目级去重。
|
||||
"""
|
||||
raw_scenes = [
|
||||
{"scene": s.scene, "duration": s.duration} for s in request.scenes
|
||||
]
|
||||
raw_scenes = [{"scene": s.scene, "duration": s.duration} for s in request.scenes]
|
||||
|
||||
results = await batch_match(
|
||||
db,
|
||||
@@ -70,8 +68,7 @@ async def batch_match_materials_endpoint(
|
||||
)
|
||||
|
||||
matched: list[MaterialInfo | None] = [
|
||||
MaterialInfo(url=r["url"], duration=r["duration"]) if r else None
|
||||
for r in results
|
||||
MaterialInfo(url=r["url"], duration=r["duration"]) if r else None for r in results
|
||||
]
|
||||
|
||||
await db.commit()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import UTC, datetime
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
@@ -14,6 +14,7 @@ from fastapi.responses import JSONResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user, get_db
|
||||
from app.core.exceptions import InsufficientPointsException
|
||||
from app.crud.point_recharge_order import point_recharge_order
|
||||
from app.crud.point_transaction import point_transaction
|
||||
from app.models.user import User
|
||||
@@ -35,6 +36,7 @@ router = APIRouter(prefix="/points", tags=["Points"])
|
||||
|
||||
# ── 余额查询 ──────────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/balance", response_model=ApiResponse[PointBalanceResponse])
|
||||
async def get_balance(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
@@ -47,6 +49,7 @@ async def get_balance(
|
||||
|
||||
# ── 流水查询 ──────────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/transactions", response_model=ApiResponse[PointTransactionListResponse])
|
||||
async def list_transactions(
|
||||
pagination: PaginationParams = Depends(),
|
||||
@@ -127,12 +130,13 @@ async def list_transactions(
|
||||
|
||||
# ── 充值 ──────────────────────────────────────────────
|
||||
|
||||
|
||||
@router.post("/recharge", response_model=ApiResponse[RechargeResponse])
|
||||
async def create_recharge_order(
|
||||
request: RechargeRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
http_request: Request = None,
|
||||
http_request: Request = None, # type: ignore[assignment]
|
||||
):
|
||||
"""
|
||||
创建积分充值订单(微信支付 Native 扫码)
|
||||
@@ -213,6 +217,7 @@ async def create_recharge_order(
|
||||
logger.error(f"[Points] 微信统一下单未返回 code_url: {wx_result}")
|
||||
order.status = "failed"
|
||||
order.error_msg = "微信未返回二维码链接"
|
||||
await db.commit()
|
||||
raise HTTPException(status_code=500, detail="微信支付下单失败")
|
||||
|
||||
order.prepay_id = wx_result.get("prepay_id")
|
||||
@@ -303,9 +308,7 @@ async def handle_wxpay_notify(
|
||||
return _wx_response()
|
||||
|
||||
# 查找订单
|
||||
order = await point_recharge_order.get_by_out_trade_no(
|
||||
db, out_trade_no=out_trade_no
|
||||
)
|
||||
order = await point_recharge_order.get_by_out_trade_no(db, out_trade_no=out_trade_no)
|
||||
if not order:
|
||||
logger.error(f"[WechatPay] 回调订单不存在: {out_trade_no}")
|
||||
return _wx_response()
|
||||
@@ -371,6 +374,7 @@ async def handle_wxpay_notify(
|
||||
await db.rollback()
|
||||
logger.exception(f"[WechatPay] 订单 {out_trade_no} 充值积分失败: {e}")
|
||||
# 记录错误但不抛出,返回 SUCCESS 避免微信重试
|
||||
order.status = "failed"
|
||||
order.error_msg = f"充值积分失败: {e}"
|
||||
await db.commit()
|
||||
|
||||
@@ -400,9 +404,7 @@ async def query_recharge_status(
|
||||
|
||||
wxpay = get_wxpay_service()
|
||||
async with httpx.AsyncClient(timeout=httpx.Timeout(30.0, connect=10.0)) as client:
|
||||
wx_result = await wxpay.query_order(
|
||||
client, out_trade_no=order.out_trade_no
|
||||
)
|
||||
wx_result = await wxpay.query_order(client, out_trade_no=order.out_trade_no)
|
||||
|
||||
order.query_result = str(wx_result)
|
||||
trade_state = wx_result.get("trade_state", "")
|
||||
@@ -465,6 +467,7 @@ async def query_recharge_status(
|
||||
|
||||
# ── 充值档位查询 ──────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/recharge-options", response_model=ApiResponse[list[dict]])
|
||||
async def get_recharge_options(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -480,6 +483,7 @@ async def get_recharge_options(
|
||||
|
||||
# ── 扣费业务类型查询 ──────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/chargeable-types", response_model=ApiResponse[list[str]])
|
||||
async def get_chargeable_types(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -496,6 +500,7 @@ async def get_chargeable_types(
|
||||
|
||||
# ── 积分规则查询 ──────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/rules", response_model=ApiResponse[list[dict]])
|
||||
async def get_points_rules(
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -530,9 +535,9 @@ async def get_points_rules(
|
||||
# ── 积分预估查询 ──────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
# ── 今日消费统计 ──────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/today-consumed", response_model=ApiResponse[dict])
|
||||
async def get_today_consumed(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
@@ -545,6 +550,7 @@ async def get_today_consumed(
|
||||
|
||||
# ── 直接消费扣费(前端/Rust 层调用)───────────────────
|
||||
|
||||
|
||||
@router.post("/consume", response_model=ApiResponse[dict])
|
||||
async def consume_points(
|
||||
request: ConsumeRequest,
|
||||
@@ -569,12 +575,12 @@ async def consume_points(
|
||||
source_type=request.source_type,
|
||||
source_id=request.source_id,
|
||||
description=f"【{request.description or request.source_type}】",
|
||||
allow_negative=False,
|
||||
allow_negative=request.allow_negative,
|
||||
)
|
||||
except ValueError as e:
|
||||
except InsufficientPointsException:
|
||||
# 余额不足(在同一事务内判断,避免竞态)
|
||||
if "积分不足" in str(e):
|
||||
raise HTTPException(status_code=402, detail=str(e))
|
||||
raise
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
await db.commit()
|
||||
|
||||
@@ -587,5 +593,3 @@ async def consume_points(
|
||||
},
|
||||
message="消费成功",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.ai.model_router import get_model_router
|
||||
from app.ai.prompts import list_categories, list_prompt_files, load_prompt, render_template
|
||||
from app.api.deps import get_current_user
|
||||
from app.core.exceptions import (
|
||||
AITimeoutException,
|
||||
InsufficientPointsException,
|
||||
PlatformError,
|
||||
PlatformErrorType,
|
||||
)
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
@@ -33,6 +39,51 @@ router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _map_platform_error(e: PlatformError) -> HTTPException:
|
||||
"""把第三方平台错误映射为用户友好的 HTTP 异常(带标准 error_code)。"""
|
||||
if e.error_type == PlatformErrorType.CONTENT_VIOLATION:
|
||||
return HTTPException(
|
||||
status_code=400,
|
||||
detail={
|
||||
"message": "人物分镜台词未通过安全审核,请修改后重试",
|
||||
"error_code": "content_violation",
|
||||
},
|
||||
)
|
||||
if e.error_type == PlatformErrorType.RATE_LIMIT:
|
||||
return HTTPException(
|
||||
status_code=429,
|
||||
detail={
|
||||
"message": "当前请求过于频繁,请稍后再试",
|
||||
"error_code": "rate_limit",
|
||||
},
|
||||
)
|
||||
if e.error_type == PlatformErrorType.TIMEOUT:
|
||||
return AITimeoutException("服务响应超时,请稍后重试")
|
||||
if e.error_type == PlatformErrorType.AUTH_FAILED:
|
||||
return HTTPException(
|
||||
status_code=401,
|
||||
detail={
|
||||
"message": "第三方服务认证失败,请稍后重试或联系客服",
|
||||
"error_code": "auth_failed",
|
||||
},
|
||||
)
|
||||
if e.error_type == PlatformErrorType.SERVER_ERROR:
|
||||
return HTTPException(
|
||||
status_code=503,
|
||||
detail={
|
||||
"message": "第三方服务繁忙,请稍后重试",
|
||||
"error_code": "server_error",
|
||||
},
|
||||
)
|
||||
return HTTPException(
|
||||
status_code=400,
|
||||
detail={
|
||||
"message": "请求失败,请检查后重试",
|
||||
"error_code": e.error_type or "unknown",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/categories", response_model=ApiResponse[list[CategoryItem]])
|
||||
async def get_categories():
|
||||
"""
|
||||
@@ -71,9 +122,8 @@ async def polish_content(
|
||||
required_points = ps._calculate_cost("polish")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
raise HTTPException(
|
||||
status_code=402,
|
||||
detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
raise InsufficientPointsException(
|
||||
f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -99,11 +149,13 @@ async def polish_content(
|
||||
data=polished,
|
||||
message=f"{type_name}润色完成",
|
||||
)
|
||||
except InsufficientPointsException:
|
||||
raise
|
||||
except HTTPException:
|
||||
raise
|
||||
except PlatformError as e:
|
||||
raise _map_platform_error(e)
|
||||
except ValueError as e:
|
||||
if "积分不足" in str(e):
|
||||
raise HTTPException(status_code=402, detail=str(e))
|
||||
logger.warning(f"[Polish] 润色失败: {e}")
|
||||
raise HTTPException(status_code=500, detail="润色失败,请检查输入内容后重试")
|
||||
except Exception as e:
|
||||
@@ -111,9 +163,6 @@ async def polish_content(
|
||||
raise HTTPException(status_code=500, detail=f"{type_name}润色失败,请稍后重试")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@router.post("/generate-title", response_model=ApiResponse[GenerateTitleResponse])
|
||||
async def generate_title(
|
||||
request: GenerateTitleRequest,
|
||||
@@ -146,7 +195,11 @@ async def generate_title(
|
||||
usage_note = "- 视频画面上的标题需要精炼,聚焦核心关键词\n- 副标题与主标题形成呼应,补充说明但不喧宾夺主"
|
||||
|
||||
# 渲染用户提示词
|
||||
title_type_desc = "大标题(主标题,提炼核心卖点,吸睛)" if request.title_type == "main" else "小标题(副标题,补充说明或制造悬念)"
|
||||
title_type_desc = (
|
||||
"大标题(主标题,提炼核心卖点,吸睛)"
|
||||
if request.title_type == "main"
|
||||
else "小标题(副标题,补充说明或制造悬念)"
|
||||
)
|
||||
user_prompt = render_template(
|
||||
user_template,
|
||||
title_type=request.title_type,
|
||||
@@ -163,9 +216,8 @@ async def generate_title(
|
||||
required_points = ps._calculate_cost("title")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
raise HTTPException(
|
||||
status_code=402,
|
||||
detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
raise InsufficientPointsException(
|
||||
f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -179,10 +231,10 @@ async def generate_title(
|
||||
|
||||
title = result.content.strip() if result.content else ""
|
||||
# 去除可能的引号
|
||||
title = title.strip('"').strip("'").strip('「」').strip('『』').strip('《》')
|
||||
title = title.strip('"').strip("'").strip("「」").strip("『』").strip("《》")
|
||||
# 截断到最大长度
|
||||
if len(title) > request.max_length:
|
||||
title = title[:request.max_length]
|
||||
title = title[: request.max_length]
|
||||
|
||||
# 扣费
|
||||
points = ps._calculate_cost("title")
|
||||
@@ -200,15 +252,15 @@ async def generate_title(
|
||||
data=GenerateTitleResponse(title=title),
|
||||
message="标题生成成功",
|
||||
)
|
||||
except InsufficientPointsException:
|
||||
raise
|
||||
except HTTPException:
|
||||
raise
|
||||
except PlatformError as e:
|
||||
raise _map_platform_error(e)
|
||||
except TimeoutError:
|
||||
logger.warning("[generate_title] 标题生成超时")
|
||||
raise HTTPException(status_code=500, detail="标题生成超时,请重试")
|
||||
except ValueError as e:
|
||||
if "积分不足" in str(e):
|
||||
raise HTTPException(status_code=402, detail=str(e))
|
||||
raise HTTPException(status_code=500, detail=f"标题生成失败: {str(e)}")
|
||||
raise AITimeoutException("标题生成超时,请稍后重试")
|
||||
except Exception as e:
|
||||
logger.error(f"[generate_title] 标题生成失败: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"标题生成失败: {str(e)}")
|
||||
|
||||
@@ -46,6 +46,3 @@ async def system_version():
|
||||
},
|
||||
message="获取版本成功",
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@ import uuid
|
||||
from typing import Literal
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field, field_validator, model_validator
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
from app.core.exceptions import InsufficientPointsException
|
||||
from app.core.redis_client import get_redis_client
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.models.user import User
|
||||
@@ -38,7 +39,6 @@ class ScriptParams(BaseModel):
|
||||
category: str = Field(..., min_length=1, description="大类代码")
|
||||
filename: str = Field(..., min_length=1, description="提示词文件名")
|
||||
|
||||
|
||||
@field_validator("category")
|
||||
@classmethod
|
||||
def validate_category(cls, v: str) -> str:
|
||||
@@ -69,6 +69,12 @@ class SubtitleParams(BaseModel):
|
||||
raise ValueError("video_path 不能为空")
|
||||
return v.strip()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_auto_align(self) -> "SubtitleParams":
|
||||
if self.mode == "auto_align" and (not self.audio_text or not self.audio_text.strip()):
|
||||
raise ValueError("auto_align 模式必须提供 audio_text")
|
||||
return self
|
||||
|
||||
|
||||
class TTSParams(BaseModel):
|
||||
"""TTS 语音合成参数"""
|
||||
@@ -96,7 +102,9 @@ class VideoParams(BaseModel):
|
||||
volume: int = Field(default=0, ge=0, le=10, description="音量")
|
||||
ref_photo_url: str | None = Field(default=None, description="人脸参考图 URL")
|
||||
planned_duration: float = Field(..., gt=0, description="该分镜脚本规划时长(秒),用于余额预检")
|
||||
total_planned_duration: float = Field(..., gt=0, description="所有分镜规划时长之和(秒),用于预检")
|
||||
total_planned_duration: float = Field(
|
||||
..., gt=0, description="所有分镜规划时长之和(秒),用于预检"
|
||||
)
|
||||
batch_id: str | None = Field(default=None, description="批次ID(可选)")
|
||||
|
||||
@field_validator("video_url")
|
||||
@@ -106,6 +114,12 @@ class VideoParams(BaseModel):
|
||||
raise ValueError("video_url 不能为空")
|
||||
return v.strip()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_audio_or_text(self) -> "VideoParams":
|
||||
if not self.audio_url and not self.text:
|
||||
raise ValueError("audio_url 和 text 必须至少填一个")
|
||||
return self
|
||||
|
||||
|
||||
class TaskCreateRequest(BaseModel):
|
||||
"""创建任务请求"""
|
||||
@@ -134,6 +148,7 @@ class TaskStatusResponse(BaseModel):
|
||||
total: int = Field(0, description="总子任务数")
|
||||
result: dict | None = Field(None, description="任务结果(完成时)")
|
||||
error: str | None = Field(None, description="错误信息(失败时)")
|
||||
error_code: str | None = Field(None, description="错误码(失败时,如 content_violation)")
|
||||
created_at: str = Field("", description="任务创建时间(ISO格式)")
|
||||
|
||||
|
||||
@@ -175,6 +190,9 @@ async def create_task(
|
||||
validated_params = {
|
||||
"category": script_validated.category,
|
||||
"filename": script_validated.filename,
|
||||
"user_id": user_id,
|
||||
"required_points": required_points,
|
||||
"project_id": project_id,
|
||||
}
|
||||
|
||||
elif task_type == "subtitle":
|
||||
@@ -222,9 +240,8 @@ async def create_task(
|
||||
f"[API] 积分不足: user={user_id}, type={task_type}, "
|
||||
f"required={required_points}, balance={check['balance']}"
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=402,
|
||||
detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
raise InsufficientPointsException(
|
||||
f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
# ── 3. 写入 Redis ──────────────────────────────────
|
||||
@@ -246,18 +263,17 @@ async def create_task(
|
||||
params=validated_params,
|
||||
)
|
||||
await registry.add_running(task_id)
|
||||
|
||||
logger.info(f"[API] Task created: {task_id}, type={task_type}, user={user_id}")
|
||||
return TaskCreateResponse(
|
||||
task_id=task_id,
|
||||
status="running",
|
||||
message=f"{task_type} 任务已创建",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[API] Failed to update registry: {e}")
|
||||
raise HTTPException(status_code=500, detail="创建任务失败:Redis写入错误")
|
||||
|
||||
logger.info(f"[API] Task created: {task_id}, type={task_type}, user={user_id}")
|
||||
return TaskCreateResponse(
|
||||
task_id=task_id,
|
||||
status="running",
|
||||
message=f"{task_type} 任务已创建",
|
||||
)
|
||||
|
||||
|
||||
@router.get("", response_model=list[TaskStatusResponse])
|
||||
async def list_tasks(
|
||||
@@ -294,6 +310,7 @@ async def list_tasks(
|
||||
total=task.total,
|
||||
result=None, # 列表查询不返回 result,避免数据过大
|
||||
error=task.error,
|
||||
error_code=task.error_code,
|
||||
created_at=task.created_at,
|
||||
)
|
||||
)
|
||||
@@ -337,6 +354,7 @@ async def get_task_status(
|
||||
total=task.total,
|
||||
result=task.result,
|
||||
error=task.error,
|
||||
error_code=task.error_code,
|
||||
created_at=task.created_at,
|
||||
)
|
||||
|
||||
|
||||
+143
-14
@@ -7,13 +7,15 @@
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Response, status
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.db.session import get_db
|
||||
from app.models.update import AppRelease, ReleasePackage
|
||||
from app.schemas.update import (
|
||||
PackageInfo,
|
||||
ReleaseCreate,
|
||||
ReleaseListItem,
|
||||
ReleaseResponse,
|
||||
@@ -38,9 +40,7 @@ async def check_update(
|
||||
如果无需更新,返回 204;如果有更新,返回 Tauri 标准格式的 JSON。
|
||||
"""
|
||||
# 查询最新版本
|
||||
result = await db.execute(
|
||||
select(AppRelease).order_by(AppRelease.release_date.desc()).limit(1)
|
||||
)
|
||||
result = await db.execute(select(AppRelease).order_by(AppRelease.release_date.desc()).limit(1))
|
||||
latest: AppRelease | None = result.scalar_one_or_none()
|
||||
|
||||
if not latest:
|
||||
@@ -52,11 +52,13 @@ async def check_update(
|
||||
|
||||
# 查询对应平台的包(优先返回 updater 用的包:有 signature 的 .app.tar.gz / .exe)
|
||||
result = await db.execute(
|
||||
select(ReleasePackage).where(
|
||||
select(ReleasePackage)
|
||||
.where(
|
||||
ReleasePackage.release_id == latest.id,
|
||||
ReleasePackage.platform == target,
|
||||
ReleasePackage.architecture == arch,
|
||||
).order_by(
|
||||
)
|
||||
.order_by(
|
||||
# 有 signature 的排前面(updater 包),空 signature 的排后面(dmg 安装包)
|
||||
ReleasePackage.signature.desc()
|
||||
)
|
||||
@@ -86,6 +88,133 @@ async def check_update(
|
||||
)
|
||||
|
||||
|
||||
def _parse_user_agent(user_agent: str | None) -> tuple[str, str] | None:
|
||||
"""
|
||||
从 User-Agent 解析 Tauri 平台标识和架构。
|
||||
|
||||
Tauri updater 使用的 platform 值为:darwin / windows / linux
|
||||
architecture 值为:x86_64 / aarch64 / i686
|
||||
"""
|
||||
if not user_agent:
|
||||
return None
|
||||
|
||||
ua = user_agent.lower()
|
||||
|
||||
# Windows
|
||||
if "windows" in ua:
|
||||
platform = "windows"
|
||||
if "arm64" in ua or "aarch64" in ua:
|
||||
arch = "aarch64"
|
||||
elif "win64" in ua or "x64" in ua:
|
||||
arch = "x86_64"
|
||||
else:
|
||||
arch = "x86_64"
|
||||
return platform, arch
|
||||
|
||||
# macOS
|
||||
if "macintosh" in ua or "mac os x" in ua:
|
||||
platform = "darwin"
|
||||
if "arm64" in ua or "aarch64" in ua:
|
||||
arch = "aarch64"
|
||||
elif "intel" in ua:
|
||||
arch = "x86_64"
|
||||
else:
|
||||
# 现代 Mac 默认按 Apple Silicon 处理;
|
||||
# 若浏览器/Rosetta 环境未暴露 arm64,可让用户手动选择
|
||||
arch = "aarch64"
|
||||
return platform, arch
|
||||
|
||||
# Linux
|
||||
if "linux" in ua:
|
||||
platform = "linux"
|
||||
if "aarch64" in ua or "arm64" in ua:
|
||||
arch = "aarch64"
|
||||
elif "x86_64" in ua or "x64" in ua:
|
||||
arch = "x86_64"
|
||||
else:
|
||||
arch = "x86_64"
|
||||
return platform, arch
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@router.get("/download")
|
||||
async def download_latest(
|
||||
request: Request,
|
||||
target: str | None = Query(None, description="平台:darwin / windows / linux"),
|
||||
arch: str | None = Query(None, description="架构:x86_64 / aarch64 / i686"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
统一下载入口:自动匹配最新版本和当前环境安装包。
|
||||
|
||||
优先级:
|
||||
1. 查询参数 target + arch(最可靠,推荐前端显式传入)
|
||||
2. User-Agent 解析(兜底)
|
||||
|
||||
返回 302 重定向到对应安装包的存储地址。
|
||||
"""
|
||||
# 1. 确定平台和架构
|
||||
if target and arch:
|
||||
platform = target.lower()
|
||||
architecture = arch.lower()
|
||||
else:
|
||||
parsed = _parse_user_agent(request.headers.get("user-agent"))
|
||||
if not parsed:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="无法识别您的操作系统,请通过官网或应用商店下载对应版本",
|
||||
)
|
||||
platform, architecture = parsed
|
||||
|
||||
# 2. 查询最新版本
|
||||
result = await db.execute(select(AppRelease).order_by(AppRelease.release_date.desc()).limit(1))
|
||||
latest: AppRelease | None = result.scalar_one_or_none()
|
||||
if not latest:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="暂无可用下载",
|
||||
)
|
||||
|
||||
# 3. 查询该平台所有包(不限制架构,因为 macOS 常用 universal 包会同时写入 x86_64/aarch64)
|
||||
result = await db.execute(
|
||||
select(ReleasePackage).where(
|
||||
ReleasePackage.release_id == latest.id,
|
||||
ReleasePackage.platform == platform,
|
||||
)
|
||||
)
|
||||
platform_pkgs = list(result.scalars().all())
|
||||
|
||||
if not platform_pkgs:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"版本 {latest.version} 暂无可用的 {platform} 安装包",
|
||||
)
|
||||
|
||||
# 4. 优先选择用户安装包,而不是 updater 用的 .app.tar.gz
|
||||
# 优先级:.dmg / .exe / .msi / .AppImage > .app.tar.gz > 其他
|
||||
def _install_pkg_priority(pkg: ReleasePackage) -> int:
|
||||
name = pkg.filename.lower()
|
||||
if name.endswith(".dmg"):
|
||||
return 1
|
||||
if name.endswith(".exe"):
|
||||
return 2
|
||||
if name.endswith(".msi"):
|
||||
return 3
|
||||
if name.endswith(".appimage"):
|
||||
return 4
|
||||
if name.endswith(".app.tar.gz"):
|
||||
return 10
|
||||
return 5
|
||||
|
||||
# 先尝试精确架构 + 高优先级安装包
|
||||
exact_arch_pkgs = [p for p in platform_pkgs if p.architecture == architecture]
|
||||
candidate_pkgs = exact_arch_pkgs or platform_pkgs
|
||||
pkg = min(candidate_pkgs, key=_install_pkg_priority)
|
||||
|
||||
return RedirectResponse(url=pkg.file_url)
|
||||
|
||||
|
||||
@router.post("/releases", response_model=ReleaseResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_release(
|
||||
release: ReleaseCreate,
|
||||
@@ -139,14 +268,14 @@ async def create_release(
|
||||
mandatory=new_release.mandatory,
|
||||
created_at=new_release.created_at,
|
||||
packages=[
|
||||
{
|
||||
"platform": p.platform,
|
||||
"architecture": p.architecture,
|
||||
"filename": p.filename,
|
||||
"file_url": p.file_url,
|
||||
"file_size": p.file_size,
|
||||
"signature": p.signature,
|
||||
}
|
||||
PackageInfo(
|
||||
platform=p.platform,
|
||||
architecture=p.architecture,
|
||||
filename=p.filename,
|
||||
file_url=p.file_url,
|
||||
file_size=p.file_size,
|
||||
signature=p.signature,
|
||||
)
|
||||
for p in new_release.packages
|
||||
],
|
||||
)
|
||||
|
||||
@@ -26,7 +26,6 @@ logger = logging.getLogger(__name__)
|
||||
settings = get_settings()
|
||||
|
||||
|
||||
|
||||
class UploadResponse(BaseModel):
|
||||
"""上传响应"""
|
||||
|
||||
@@ -103,8 +102,8 @@ async def upload_video(
|
||||
domain=domain,
|
||||
)
|
||||
|
||||
url = result.get("url")
|
||||
key = result.get("key")
|
||||
url = result.get("url") or ""
|
||||
key = result.get("key") or ""
|
||||
|
||||
if not url:
|
||||
raise HTTPException(status_code=500, detail="上传到七牛云失败:未返回 URL")
|
||||
@@ -126,8 +125,6 @@ async def upload_video(
|
||||
raise HTTPException(status_code=500, detail=f"上传失败: {e}")
|
||||
|
||||
|
||||
|
||||
|
||||
@router.post("/audio", response_model=ApiResponse[UploadResponse])
|
||||
async def upload_audio(
|
||||
file: UploadFile = File(..., description="音频文件"),
|
||||
@@ -198,8 +195,8 @@ async def upload_audio(
|
||||
domain=domain,
|
||||
)
|
||||
|
||||
url = result.get("url")
|
||||
key = result.get("key")
|
||||
url = result.get("url") or ""
|
||||
key = result.get("key") or ""
|
||||
|
||||
if not url:
|
||||
raise HTTPException(status_code=500, detail="上传到七牛云失败:未返回 URL")
|
||||
|
||||
@@ -18,6 +18,10 @@ from app.core.exceptions import PlatformError
|
||||
from app.core.redis_client import get_redis_client
|
||||
from app.platform_gateway import PlatformGateway
|
||||
from app.schemas.common import success_response
|
||||
from app.utils.content_fingerprint import (
|
||||
extract_vidu_error_code,
|
||||
is_vidu_audit_error,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -44,10 +48,12 @@ async def vidu_callback(request: Request):
|
||||
headers_dict = dict(request.headers)
|
||||
|
||||
# 使用 APP_BASE_URL 构建 callback_url,确保与提交任务时传给 Vidu 的一致
|
||||
#(Nginx 反向代理可能导致 request.url 的 scheme 为 http,与 Vidu 签名时的 https 不一致)
|
||||
# (Nginx 反向代理可能导致 request.url 的 scheme 为 http,与 Vidu 签名时的 https 不一致)
|
||||
app_base_url = get_settings().app_base_url
|
||||
callback_url = f"{app_base_url}/api/v1/vidu/callback" if app_base_url else str(request.url)
|
||||
logger.info(f"[Vidu] 收到回调: request_url={request.url}, callback_url={callback_url}, body={body_bytes.decode('utf-8', errors='replace')[:500]}")
|
||||
logger.info(
|
||||
f"[Vidu] 收到回调: request_url={request.url}, callback_url={callback_url}, body={body_bytes.decode('utf-8', errors='replace')[:500]}"
|
||||
)
|
||||
|
||||
try:
|
||||
task_status = await gateway.handle_webhook(
|
||||
@@ -64,15 +70,13 @@ async def vidu_callback(request: Request):
|
||||
logger.error(f"[Vidu] 回调处理失败: {e}")
|
||||
raise HTTPException(status_code=500, detail="回调处理失败,请稍后重试")
|
||||
|
||||
logger.info(f"[Vidu] 回调解析完成: state={task_status.state}, result={task_status.result}, error={task_status.error_message}")
|
||||
logger.info(
|
||||
f"[Vidu] 回调解析完成: state={task_status.state}, result={task_status.result}, error={task_status.error_message}"
|
||||
)
|
||||
|
||||
# 2. 通过 platform_task_id 反查 Async Engine 内部 task_id,更新 TaskRegistry
|
||||
platform_task_id = (
|
||||
task_status.result.get("task_id") if task_status.result else None
|
||||
)
|
||||
video_url = (
|
||||
task_status.result.get("video_url") if task_status.result else None
|
||||
)
|
||||
platform_task_id = task_status.result.get("task_id") if task_status.result else None
|
||||
video_url = task_status.result.get("video_url") if task_status.result else None
|
||||
|
||||
logger.info(f"[Vidu] 准备反查 internal_task_id: platform_task_id={platform_task_id}")
|
||||
|
||||
@@ -105,12 +109,23 @@ async def vidu_callback(request: Request):
|
||||
result={"video_url": video_url, "state": "success"},
|
||||
)
|
||||
elif task_status.state == "failed":
|
||||
await registry.update(
|
||||
internal_task_id,
|
||||
status="failed",
|
||||
message="视频生成失败",
|
||||
error=task_status.error_message or "视频生成失败",
|
||||
)
|
||||
error_message = task_status.error_message or "视频生成失败"
|
||||
err_code = extract_vidu_error_code(error_message)
|
||||
is_audit = err_code and is_vidu_audit_error(err_code)
|
||||
|
||||
update_kwargs = {
|
||||
"status": "failed",
|
||||
"message": (
|
||||
"人物分镜台词未通过安全审核,请修改后重试"
|
||||
if is_audit
|
||||
else "视频生成失败"
|
||||
),
|
||||
"error": error_message,
|
||||
}
|
||||
if is_audit:
|
||||
update_kwargs["error_code"] = "content_violation"
|
||||
|
||||
await registry.update(internal_task_id, **update_kwargs)
|
||||
logger.info(
|
||||
f"[Vidu] 回调已更新 TaskRegistry: task={internal_task_id}, "
|
||||
f"state={task_status.state}, video_url={video_url}"
|
||||
@@ -121,8 +136,6 @@ async def vidu_callback(request: Request):
|
||||
f"platform={platform_task_id}"
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"[Vidu] 回调无法反查内部 task_id: platform={platform_task_id}"
|
||||
)
|
||||
logger.warning(f"[Vidu] 回调无法反查内部 task_id: platform={platform_task_id}")
|
||||
|
||||
return success_response(message="回调已接收")
|
||||
|
||||
@@ -10,12 +10,13 @@ import logging
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
from app.core.exceptions import PlatformError
|
||||
from app.core.exceptions import InsufficientPointsException, PlatformError
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.schemas.common import ApiResponse, success_response
|
||||
@@ -49,7 +50,9 @@ class TTSSynthesizeRequest(BaseModel):
|
||||
class VoiceCloneSubmitRequest(BaseModel):
|
||||
"""声音复刻提交请求"""
|
||||
|
||||
source_audio_url: str | None = Field(None, description="源音频 URL(5-30秒,mp3/wav,需公开可访问)")
|
||||
source_audio_url: str | None = Field(
|
||||
None, description="源音频 URL(5-30秒,mp3/wav,需公开可访问)"
|
||||
)
|
||||
source_video_url: str | None = Field(None, description="源视频 URL(可选)")
|
||||
video_id: str | None = Field(None, description="历史作品ID(可选)")
|
||||
voice_name: str | None = Field(None, description="自定义音色名称(≤20字符)")
|
||||
@@ -111,7 +114,7 @@ async def synthesize_speech(
|
||||
# 宽松预检:余额为负或零时阻止,避免浪费第三方资源
|
||||
balance_info = await ps.get_user_balance(db, current_user.id)
|
||||
if balance_info["balance"] <= 0:
|
||||
raise HTTPException(status_code=402, detail="余额不足,请先充值")
|
||||
raise InsufficientPointsException("余额不足,请先充值")
|
||||
|
||||
try:
|
||||
audio_url = await service.synthesize(
|
||||
@@ -122,7 +125,7 @@ async def synthesize_speech(
|
||||
pitch=request.pitch,
|
||||
)
|
||||
|
||||
# 探测音频时长并扣费
|
||||
# 探测音频时长并扣费(计费成功才返回结果)
|
||||
try:
|
||||
seconds = await get_audio_duration(audio_url)
|
||||
points = ps._calculate_cost("tts", {"seconds": seconds})
|
||||
@@ -137,24 +140,26 @@ async def synthesize_speech(
|
||||
allow_negative=True,
|
||||
)
|
||||
await db.commit()
|
||||
except ValueError as e:
|
||||
if "积分不足" in str(e):
|
||||
raise HTTPException(status_code=402, detail=str(e))
|
||||
logger.error(f"[Voice] TTS 扣费失败: {e}")
|
||||
|
||||
return success_response(
|
||||
data={
|
||||
"audio_url": audio_url,
|
||||
"format": "mp3",
|
||||
"text": request.text,
|
||||
"voice_id": request.voice_id or DEFAULT_VOICE_ID,
|
||||
"consumed_points": points,
|
||||
"duration": seconds,
|
||||
},
|
||||
message="合成成功",
|
||||
)
|
||||
except InsufficientPointsException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"[Voice] TTS 扣费失败: {e}")
|
||||
|
||||
return success_response(
|
||||
data={
|
||||
"audio_url": audio_url,
|
||||
"format": "mp3",
|
||||
"text": request.text,
|
||||
"voice_id": request.voice_id or DEFAULT_VOICE_ID,
|
||||
"consumed_points": points,
|
||||
"duration": seconds,
|
||||
},
|
||||
message="合成成功",
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="语音合成计费失败,请稍后重试",
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
@@ -165,7 +170,6 @@ async def synthesize_speech(
|
||||
raise HTTPException(status_code=500, detail="语音合成失败,请稍后重试")
|
||||
|
||||
|
||||
|
||||
def _normalize_voice_id(name: str | None) -> str:
|
||||
"""
|
||||
将用户输入的名称规范化为 Vidu 合法的 voice_id。
|
||||
@@ -220,9 +224,8 @@ async def submit_clone_task(
|
||||
required_points = ps._calculate_cost("voice_clone")
|
||||
check = await ps.check_balance(db, current_user.id, required_points)
|
||||
if not check["sufficient"]:
|
||||
raise HTTPException(
|
||||
status_code=402,
|
||||
detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}",
|
||||
raise InsufficientPointsException(
|
||||
f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}"
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -244,10 +247,8 @@ async def submit_clone_task(
|
||||
description="【声音复刻】",
|
||||
)
|
||||
await db.commit()
|
||||
except ValueError as e:
|
||||
if "积分不足" in str(e):
|
||||
raise HTTPException(status_code=402, detail=str(e))
|
||||
logger.error(f"[Voice] 克隆扣费失败: {e}")
|
||||
except InsufficientPointsException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"[Voice] 克隆扣费失败: {e}")
|
||||
|
||||
@@ -292,5 +293,3 @@ async def query_clone_task(
|
||||
),
|
||||
message="克隆已完成",
|
||||
)
|
||||
|
||||
|
||||
|
||||
+11
-17
@@ -24,7 +24,7 @@ class Settings(BaseSettings):
|
||||
|
||||
# 应用基础配置
|
||||
APP_NAME: str = Field(default="美家卡智影 API", description="应用名称")
|
||||
APP_VERSION: str = Field(default="1.8.0", description="应用版本")
|
||||
APP_VERSION: str = Field(default="1.9.1", description="应用版本")
|
||||
DEBUG: bool = Field(default=False, description="调试模式")
|
||||
ENV: Literal["development", "staging", "production"] = Field(
|
||||
default="development", description="运行环境"
|
||||
@@ -45,7 +45,9 @@ class Settings(BaseSettings):
|
||||
description="数据库连接字符串(PostgreSQL)",
|
||||
)
|
||||
DATABASE_POOL_SIZE: int = Field(default=10, description="数据库连接池常驻连接数")
|
||||
DATABASE_MAX_OVERFLOW: int = Field(default=10, description="连接池临时溢出上限(建议 ≤ pool_size)")
|
||||
DATABASE_MAX_OVERFLOW: int = Field(
|
||||
default=10, description="连接池临时溢出上限(建议 ≤ pool_size)"
|
||||
)
|
||||
DATABASE_POOL_RECYCLE: int = Field(
|
||||
default=1800, description="连接回收时间(秒),防止长连接被数据库静默断开"
|
||||
)
|
||||
@@ -73,7 +75,7 @@ class Settings(BaseSettings):
|
||||
|
||||
# 安全配置
|
||||
SECRET_KEY: str = Field(
|
||||
...,
|
||||
default="",
|
||||
description="JWT 签名密钥(生产环境必须修改)",
|
||||
)
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = Field(
|
||||
@@ -107,7 +109,9 @@ class Settings(BaseSettings):
|
||||
VOLCENGINE_CAPTION_TOKEN: str | None = Field(default=None, description="火山字幕 Token")
|
||||
|
||||
# 火山引擎 MediaKit 服务(背景移除等多媒体处理)
|
||||
VOLCENGINE_MEDIAKIT_TOKEN: str | None = Field(default=None, description="火山引擎 MediaKit Token")
|
||||
VOLCENGINE_MEDIAKIT_TOKEN: str | None = Field(
|
||||
default=None, description="火山引擎 MediaKit Token"
|
||||
)
|
||||
|
||||
# Vidu 密钥(base_url 已从 Settings 移除,改用 config/platform-config.yaml 配置)
|
||||
VIDU_API_KEY: str | None = Field(default=None, description="Vidu API Key")
|
||||
@@ -124,9 +128,7 @@ class Settings(BaseSettings):
|
||||
WXPAY_MCHID: str | None = Field(default=None, description="微信支付商户号")
|
||||
WXPAY_APPID: str | None = Field(default=None, description="微信支付 AppID")
|
||||
WXPAY_API_KEY: str | None = Field(default=None, description="微信支付 APIv2 密钥")
|
||||
WXPAY_NOTIFY_URL: str | None = Field(
|
||||
default=None, description="微信支付回调地址(完整 URL)"
|
||||
)
|
||||
WXPAY_NOTIFY_URL: str | None = Field(default=None, description="微信支付回调地址(完整 URL)")
|
||||
|
||||
# B2M 短信平台配置
|
||||
SMS_APP_ID: str | None = Field(default=None, description="B2M 短信平台 AppID")
|
||||
@@ -134,16 +136,12 @@ class Settings(BaseSettings):
|
||||
SMS_BASE_URL: str | None = Field(
|
||||
default=None, description="B2M 短信平台接口地址(如 http://sms.b2m.cn:8080)"
|
||||
)
|
||||
SMS_EXTENDED_CODE: str | None = Field(
|
||||
default=None, description="B2M 短信平台扩展码(选填)"
|
||||
)
|
||||
SMS_EXTENDED_CODE: str | None = Field(default=None, description="B2M 短信平台扩展码(选填)")
|
||||
SMS_CODE_WHITELIST: str = Field(
|
||||
default="",
|
||||
description="免验证码登录白名单(逗号分隔的手机号,如 13800138000,13900139000)",
|
||||
)
|
||||
|
||||
|
||||
|
||||
# 文件上传限制(字节)
|
||||
UPLOAD_MAX_VIDEO_SIZE: int = Field(
|
||||
default=500 * 1024 * 1024, description="视频最大上传大小(字节)"
|
||||
@@ -187,11 +185,7 @@ class Settings(BaseSettings):
|
||||
"""免验证码登录白名单(去重、去空格)"""
|
||||
if not self.SMS_CODE_WHITELIST:
|
||||
return set()
|
||||
return {
|
||||
mobile.strip()
|
||||
for mobile in self.SMS_CODE_WHITELIST.split(",")
|
||||
if mobile.strip()
|
||||
}
|
||||
return {mobile.strip() for mobile in self.SMS_CODE_WHITELIST.split(",") if mobile.strip()}
|
||||
|
||||
|
||||
@lru_cache
|
||||
|
||||
@@ -24,9 +24,16 @@ class AppException(HTTPException):
|
||||
status_code: int,
|
||||
message: str = "操作失败",
|
||||
detail: dict | None = None,
|
||||
*,
|
||||
error_code: str | None = None,
|
||||
):
|
||||
super().__init__(status_code=status_code, detail=detail or {})
|
||||
body = detail or {}
|
||||
body["message"] = message
|
||||
if error_code:
|
||||
body["error_code"] = error_code
|
||||
super().__init__(status_code=status_code, detail=body)
|
||||
self.message = message
|
||||
self.error_code = error_code
|
||||
|
||||
|
||||
class NotFoundException(AppException):
|
||||
@@ -44,7 +51,7 @@ class ValidationException(AppException):
|
||||
|
||||
def __init__(self, message: str = "参数验证失败"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||
message=message,
|
||||
)
|
||||
|
||||
@@ -79,6 +86,17 @@ class BusinessException(AppException):
|
||||
)
|
||||
|
||||
|
||||
class InsufficientPointsException(AppException):
|
||||
"""积分不足"""
|
||||
|
||||
def __init__(self, message: str = "积分不足"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_402_PAYMENT_REQUIRED,
|
||||
message=message,
|
||||
error_code="insufficient_points",
|
||||
)
|
||||
|
||||
|
||||
class ModelUnavailableException(AppException):
|
||||
"""AI 模型不可用"""
|
||||
|
||||
@@ -99,6 +117,50 @@ class TaskFailedException(AppException):
|
||||
)
|
||||
|
||||
|
||||
class PromptNotFoundException(AppException):
|
||||
"""提示词文件不存在"""
|
||||
|
||||
def __init__(self, message: str = "未找到提示词"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
message=message,
|
||||
error_code="prompt_not_found",
|
||||
)
|
||||
|
||||
|
||||
class AIEmptyResponseException(AppException):
|
||||
"""AI 返回内容为空"""
|
||||
|
||||
def __init__(self, message: str = "AI 返回内容为空"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
message=message,
|
||||
error_code="empty_result",
|
||||
)
|
||||
|
||||
|
||||
class AIParseErrorException(AppException):
|
||||
"""AI 返回内容解析失败"""
|
||||
|
||||
def __init__(self, message: str = "AI 返回格式解析失败"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
message=message,
|
||||
error_code="parse_error",
|
||||
)
|
||||
|
||||
|
||||
class AITimeoutException(AppException):
|
||||
"""AI 调用超时"""
|
||||
|
||||
def __init__(self, message: str = "AI 请求超时,请稍后重试"):
|
||||
super().__init__(
|
||||
status_code=status.HTTP_504_GATEWAY_TIMEOUT,
|
||||
message=message,
|
||||
error_code="timeout",
|
||||
)
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 第三方平台异常(PlatformError 体系)
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
@@ -111,14 +173,15 @@ class PlatformErrorType:
|
||||
确保前端和网关能够统一处理。
|
||||
"""
|
||||
|
||||
RATE_LIMIT = "rate_limit" # 429,可重试
|
||||
AUTH_FAILED = "auth_failed" # 401/403,不可重试
|
||||
TIMEOUT = "timeout" # 连接/读取超时,可重试
|
||||
SERVER_ERROR = "server_error" # 第三方 5xx,可重试
|
||||
BAD_REQUEST = "bad_request" # 参数错误,不可重试
|
||||
RATE_LIMIT = "rate_limit" # 429,可重试
|
||||
AUTH_FAILED = "auth_failed" # 401/403,不可重试
|
||||
TIMEOUT = "timeout" # 连接/读取超时,可重试
|
||||
SERVER_ERROR = "server_error" # 第三方 5xx,可重试
|
||||
BAD_REQUEST = "bad_request" # 参数错误,不可重试
|
||||
QUOTA_EXHAUSTED = "quota_exhausted" # 额度用完,不可重试(或延迟重试)
|
||||
NOT_FOUND = "not_found" # 资源不存在,不可重试
|
||||
UNKNOWN = "unknown" # 兜底
|
||||
NOT_FOUND = "not_found" # 资源不存在,不可重试
|
||||
CONTENT_VIOLATION = "content_violation" # 内容安全/审核不通过,不可重试
|
||||
UNKNOWN = "unknown" # 兜底
|
||||
|
||||
|
||||
class PlatformError(Exception):
|
||||
@@ -145,12 +208,14 @@ class PlatformError(Exception):
|
||||
retryable: bool = False,
|
||||
error_type: str = PlatformErrorType.UNKNOWN,
|
||||
status_code: int | None = None,
|
||||
raw_code: str | None = None,
|
||||
):
|
||||
super().__init__(message)
|
||||
self.platform = platform
|
||||
self.retryable = retryable
|
||||
self.error_type = error_type
|
||||
self.status_code = status_code
|
||||
self.raw_code = raw_code
|
||||
|
||||
def to_http_status(self) -> int:
|
||||
"""根据 error_type 和 retryable 返回标准 HTTP 状态码"""
|
||||
@@ -161,6 +226,7 @@ class PlatformError(Exception):
|
||||
PlatformErrorType.AUTH_FAILED: 401,
|
||||
PlatformErrorType.BAD_REQUEST: 400,
|
||||
PlatformErrorType.NOT_FOUND: 404,
|
||||
PlatformErrorType.CONTENT_VIOLATION: 400,
|
||||
}
|
||||
if self.error_type in mapping:
|
||||
return mapping[self.error_type]
|
||||
|
||||
@@ -143,9 +143,7 @@ class PlatformConfigLoader:
|
||||
启动时加载,全环境只读(不支持热重载)。
|
||||
"""
|
||||
|
||||
DEFAULT_CONFIG_PATH = (
|
||||
Path(__file__).parent.parent.parent / "config" / "platform-config.yaml"
|
||||
)
|
||||
DEFAULT_CONFIG_PATH = Path(__file__).parent.parent.parent / "config" / "platform-config.yaml"
|
||||
|
||||
def __init__(self, config_path: str | None = None):
|
||||
self.config_path = Path(config_path) if config_path else self.DEFAULT_CONFIG_PATH
|
||||
@@ -157,9 +155,7 @@ class PlatformConfigLoader:
|
||||
def _load(self) -> None:
|
||||
"""加载并校验配置文件"""
|
||||
if not self.config_path.exists():
|
||||
raise FileNotFoundError(
|
||||
f"平台配置文件不存在: {self.config_path}"
|
||||
)
|
||||
raise FileNotFoundError(f"平台配置文件不存在: {self.config_path}")
|
||||
|
||||
try:
|
||||
with open(self.config_path, encoding="utf-8") as f:
|
||||
@@ -215,18 +211,10 @@ class PlatformConfigLoader:
|
||||
return [m for m in self._models.values() if m.is_enabled]
|
||||
|
||||
def get_models_by_capability(self, capability: str) -> list[ModelConfig]:
|
||||
return [
|
||||
m
|
||||
for m in self._models.values()
|
||||
if m.is_enabled and capability in m.capabilities
|
||||
]
|
||||
return [m for m in self._models.values() if m.is_enabled and capability in m.capabilities]
|
||||
|
||||
def get_models_by_platform(self, platform_id: str) -> list[ModelConfig]:
|
||||
return [
|
||||
m
|
||||
for m in self._models.values()
|
||||
if m.platform_id == platform_id and m.is_enabled
|
||||
]
|
||||
return [m for m in self._models.values() if m.platform_id == platform_id and m.is_enabled]
|
||||
|
||||
def get_default_model_for_task(self, task_type: str) -> str | None:
|
||||
if self._raw is None:
|
||||
|
||||
@@ -4,6 +4,8 @@ Redis 客户端
|
||||
全局 Redis 连接,供 Scheduler 和 RateLimiter 使用
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from redis.asyncio import Redis
|
||||
|
||||
from app.config import get_settings
|
||||
@@ -19,7 +21,7 @@ def get_redis_client() -> Redis:
|
||||
settings = get_settings()
|
||||
|
||||
# 构建连接参数
|
||||
client_kwargs = {
|
||||
client_kwargs: dict[str, Any] = {
|
||||
"host": settings.REDIS_HOST,
|
||||
"port": settings.REDIS_PORT,
|
||||
"db": settings.REDIS_DB,
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
"""
|
||||
安全工具 - JWT Token 生成与验证
|
||||
===============================
|
||||
安全工具 - JWT Token 生成与验证 + 密码哈希
|
||||
==========================================
|
||||
|
||||
支持双 Token 体系:
|
||||
- Access Token:短效(30 分钟),用于 API 请求认证
|
||||
- Refresh Token:长效(30 天),用于换取新的 Access Token
|
||||
|
||||
密码哈希:
|
||||
- 使用 bcrypt 进行密码哈希和校验
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -15,11 +18,25 @@ from typing import Any
|
||||
|
||||
import jwt
|
||||
from jwt import PyJWTError
|
||||
from passlib.context import CryptContext
|
||||
|
||||
from app.config import get_settings
|
||||
|
||||
settings = get_settings()
|
||||
|
||||
# bcrypt 密码哈希上下文
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
|
||||
def hash_password(password: str) -> str:
|
||||
"""对明文密码进行 bcrypt 哈希"""
|
||||
return pwd_context.hash(password)
|
||||
|
||||
|
||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
||||
"""校验明文密码与哈希密码是否匹配"""
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
|
||||
def create_access_token(data: dict[str, Any], expires_delta: timedelta | None = None) -> str:
|
||||
"""
|
||||
|
||||
@@ -70,6 +70,16 @@ class BrollCategoryCRUD(CRUDBase[BrollCategory]):
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_by_level(self, db: AsyncSession, *, level: int) -> list[BrollCategory]:
|
||||
"""根据层级获取所有启用的分类"""
|
||||
result = await db.execute(
|
||||
select(BrollCategory).where(
|
||||
BrollCategory.level == level,
|
||||
BrollCategory.status == "active",
|
||||
)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
# 导出实例
|
||||
broll_category = BrollCategoryCRUD()
|
||||
|
||||
@@ -49,9 +49,7 @@ class BrollMaterialCRUD(CRUDBase[BrollMaterial]):
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def increment_usage_count(
|
||||
self, db: AsyncSession, *, material_id: int
|
||||
) -> None:
|
||||
async def increment_usage_count(self, db: AsyncSession, *, material_id: int) -> None:
|
||||
"""
|
||||
原子递增素材使用次数
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@ class PointRechargeOrderCRUD(CRUDBase[PointRechargeOrder]):
|
||||
) -> PointRechargeOrder | None:
|
||||
"""根据商户订单号查询"""
|
||||
result = await db.execute(
|
||||
select(PointRechargeOrder).where(
|
||||
PointRechargeOrder.out_trade_no == out_trade_no
|
||||
)
|
||||
select(PointRechargeOrder).where(PointRechargeOrder.out_trade_no == out_trade_no)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
@@ -34,9 +32,7 @@ class PointRechargeOrderCRUD(CRUDBase[PointRechargeOrder]):
|
||||
) -> PointRechargeOrder | None:
|
||||
"""根据微信支付订单号查询"""
|
||||
result = await db.execute(
|
||||
select(PointRechargeOrder).where(
|
||||
PointRechargeOrder.wx_order_no == wx_order_no
|
||||
)
|
||||
select(PointRechargeOrder).where(PointRechargeOrder.wx_order_no == wx_order_no)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"""
|
||||
|
||||
from datetime import datetime, time
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -24,7 +25,7 @@ class PointTransactionCRUD(CRUDBase[PointTransaction]):
|
||||
self,
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: str,
|
||||
user_id: UUID | str,
|
||||
skip: int = 0,
|
||||
limit: int = 50,
|
||||
tx_type: str | None = None,
|
||||
@@ -55,7 +56,7 @@ class PointTransactionCRUD(CRUDBase[PointTransaction]):
|
||||
self,
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: str,
|
||||
user_id: UUID | str,
|
||||
tx_type: str | None = None,
|
||||
category: str | None = None,
|
||||
source_type: str | None = None,
|
||||
@@ -105,18 +106,15 @@ class PointTransactionCRUD(CRUDBase[PointTransaction]):
|
||||
self,
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: str,
|
||||
user_id: UUID | str,
|
||||
) -> int:
|
||||
"""统计用户今日消费积分总和"""
|
||||
now = datetime.now()
|
||||
start_of_day = datetime.combine(now.date(), time.min)
|
||||
stmt = (
|
||||
select(func.coalesce(func.sum(PointTransaction.amount), 0))
|
||||
.where(
|
||||
PointTransaction.user_id == user_id,
|
||||
PointTransaction.type == "consume",
|
||||
PointTransaction.created_at >= start_of_day,
|
||||
)
|
||||
stmt = select(func.coalesce(func.sum(PointTransaction.amount), 0)).where(
|
||||
PointTransaction.user_id == user_id,
|
||||
PointTransaction.type == "consume",
|
||||
PointTransaction.created_at >= start_of_day,
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
return result.scalar() or 0
|
||||
|
||||
+21
-10
@@ -5,7 +5,11 @@
|
||||
用户认证相关的数据访问。
|
||||
"""
|
||||
|
||||
from typing import Any, cast
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.engine import CursorResult
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.crud.base import CRUDBase
|
||||
@@ -48,7 +52,7 @@ class UserCRUD(CRUDBase[User]):
|
||||
return user
|
||||
|
||||
async def update_login_info(
|
||||
self, db: AsyncSession, *, user_id: str, ip: str | None = None
|
||||
self, db: AsyncSession, *, user_id: UUID | str, ip: str | None = None
|
||||
) -> User | None:
|
||||
"""
|
||||
更新用户最后登录信息
|
||||
@@ -67,9 +71,20 @@ class UserCRUD(CRUDBase[User]):
|
||||
await db.refresh(user)
|
||||
return user
|
||||
|
||||
async def update_extra(
|
||||
self, db: AsyncSession, *, user_id: str, extra: dict
|
||||
) -> bool:
|
||||
async def update_password(
|
||||
self, db: AsyncSession, *, user_id: UUID | str, password_hash: str
|
||||
) -> User | None:
|
||||
"""更新用户密码"""
|
||||
user = await self.get(db, id=user_id)
|
||||
if user is None:
|
||||
return None
|
||||
|
||||
user.password_hash = password_hash
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
return user
|
||||
|
||||
async def update_extra(self, db: AsyncSession, *, user_id: UUID | str, extra: dict) -> bool:
|
||||
"""
|
||||
原子更新用户 extra 字段(JSONB)
|
||||
|
||||
@@ -77,12 +92,8 @@ class UserCRUD(CRUDBase[User]):
|
||||
"""
|
||||
from sqlalchemy import update
|
||||
|
||||
stmt = (
|
||||
update(User)
|
||||
.where(User.id == user_id)
|
||||
.values(extra=extra)
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
stmt = update(User).where(User.id == user_id).values(extra=extra)
|
||||
result = cast(CursorResult[Any], await db.execute(stmt))
|
||||
await db.commit()
|
||||
return result.rowcount > 0
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
核心操作是「覆盖」而非「新增」,使用 INSERT ... ON CONFLICT DO UPDATE 保证原子性。
|
||||
"""
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -20,18 +22,16 @@ class UserDeviceCRUD(CRUDBase[UserDevice]):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(UserDevice)
|
||||
|
||||
async def get_by_user_id(self, db: AsyncSession, *, user_id: str) -> UserDevice | None:
|
||||
async def get_by_user_id(self, db: AsyncSession, *, user_id: UUID | str) -> UserDevice | None:
|
||||
"""根据用户 ID 获取设备记录"""
|
||||
result = await db.execute(
|
||||
select(UserDevice).where(UserDevice.user_id == user_id)
|
||||
)
|
||||
result = await db.execute(select(UserDevice).where(UserDevice.user_id == user_id))
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def create_or_update(
|
||||
self,
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: str,
|
||||
user_id: UUID | str,
|
||||
device_id: str,
|
||||
device_name: str | None = None,
|
||||
os_info: str | None = None,
|
||||
@@ -80,12 +80,10 @@ class UserDeviceCRUD(CRUDBase[UserDevice]):
|
||||
await db.commit()
|
||||
|
||||
# 返回最新的记录
|
||||
result = await db.execute(
|
||||
select(UserDevice).where(UserDevice.user_id == user_id)
|
||||
)
|
||||
result = await db.execute(select(UserDevice).where(UserDevice.user_id == user_id))
|
||||
return result.scalar_one()
|
||||
|
||||
async def delete_by_user_id(self, db: AsyncSession, *, user_id: str) -> bool:
|
||||
async def delete_by_user_id(self, db: AsyncSession, *, user_id: UUID | str) -> bool:
|
||||
"""根据用户 ID 删除设备记录(登出时使用)"""
|
||||
device = await self.get_by_user_id(db, user_id=user_id)
|
||||
if device is None:
|
||||
@@ -100,9 +98,7 @@ class UserDeviceCRUD(CRUDBase[UserDevice]):
|
||||
) -> UserDevice | None:
|
||||
"""根据 Refresh Token 哈希获取设备记录"""
|
||||
result = await db.execute(
|
||||
select(UserDevice).where(
|
||||
UserDevice.refresh_token_hash == refresh_token_hash
|
||||
)
|
||||
select(UserDevice).where(UserDevice.refresh_token_hash == refresh_token_hash)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
|
||||
@@ -149,12 +149,8 @@ async def lifespan(app: FastAPI):
|
||||
logger.info("VolcengineMediakitAdapter initialized")
|
||||
|
||||
if app.state.volcengine_provider:
|
||||
app.state.volcengine_ark_adapter = VolcengineArkAdapter(
|
||||
app.state.volcengine_provider
|
||||
)
|
||||
app.state.platform_gateway.register(
|
||||
"volcengine_ark", app.state.volcengine_ark_adapter
|
||||
)
|
||||
app.state.volcengine_ark_adapter = VolcengineArkAdapter(app.state.volcengine_provider)
|
||||
app.state.platform_gateway.register("volcengine_ark", app.state.volcengine_ark_adapter)
|
||||
logger.info("VolcengineArkAdapter registered to PlatformGateway")
|
||||
|
||||
logger.info("PlatformGateway initialized")
|
||||
@@ -177,9 +173,7 @@ async def lifespan(app: FastAPI):
|
||||
logger.info("Vidu Service initialized")
|
||||
|
||||
if app.state.volcengine_caption_provider:
|
||||
app.state.volcengine_caption_service = VolcengineCaptionService(
|
||||
app.state.platform_gateway
|
||||
)
|
||||
app.state.volcengine_caption_service = VolcengineCaptionService(app.state.platform_gateway)
|
||||
logger.info("Volcengine Caption Service initialized")
|
||||
else:
|
||||
app.state.volcengine_caption_service = None
|
||||
@@ -276,12 +270,14 @@ def create_app() -> FastAPI:
|
||||
"code": exc.status_code or http_status,
|
||||
"message": str(exc),
|
||||
"data": None,
|
||||
"error_code": exc.error_type,
|
||||
}
|
||||
if settings.DEBUG:
|
||||
content["detail"] = {
|
||||
"platform": exc.platform,
|
||||
"error_type": exc.error_type,
|
||||
"retryable": exc.retryable,
|
||||
"raw_code": exc.raw_code,
|
||||
}
|
||||
return _cors_response(request, http_status, content)
|
||||
|
||||
@@ -294,6 +290,9 @@ def create_app() -> FastAPI:
|
||||
exc.detail if isinstance(exc.detail, str) else "请求失败"
|
||||
)
|
||||
detail = exc.detail if isinstance(exc.detail, dict) else None
|
||||
error_code = getattr(exc, "error_code", None)
|
||||
if not error_code and isinstance(detail, dict):
|
||||
error_code = detail.get("error_code")
|
||||
|
||||
return _cors_response(
|
||||
request,
|
||||
@@ -301,6 +300,7 @@ def create_app() -> FastAPI:
|
||||
{
|
||||
"code": exc.status_code,
|
||||
"message": message,
|
||||
"error_code": error_code,
|
||||
"detail": detail,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -33,18 +33,10 @@ class BgmMusic(BaseModelBigInt):
|
||||
category: Mapped[str] = mapped_column(
|
||||
String(32), nullable=False, index=True, comment="场景分类"
|
||||
)
|
||||
file_path: Mapped[str] = mapped_column(
|
||||
String(512), nullable=False, comment="相对文件路径"
|
||||
)
|
||||
url: Mapped[str] = mapped_column(
|
||||
String(1024), nullable=False, comment="七牛云 URL"
|
||||
)
|
||||
duration: Mapped[float] = mapped_column(
|
||||
Float, nullable=True, comment="时长(秒)"
|
||||
)
|
||||
file_path: Mapped[str] = mapped_column(String(512), nullable=False, comment="相对文件路径")
|
||||
url: Mapped[str] = mapped_column(String(1024), nullable=False, comment="七牛云 URL")
|
||||
duration: Mapped[float] = mapped_column(Float, nullable=True, comment="时长(秒)")
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(16), default="active", nullable=False, comment="状态: active/inactive"
|
||||
)
|
||||
sort_order: Mapped[int] = mapped_column(
|
||||
Integer, default=0, nullable=False, comment="排序权重"
|
||||
)
|
||||
sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="排序权重")
|
||||
|
||||
@@ -7,7 +7,16 @@ Tauri updater 插件所需的数据结构。
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from sqlalchemy import Boolean, BigInteger, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint
|
||||
from sqlalchemy import (
|
||||
BigInteger,
|
||||
Boolean,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
String,
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.db.session import Base
|
||||
@@ -60,5 +69,11 @@ class ReleasePackage(Base):
|
||||
release: Mapped["AppRelease"] = relationship("AppRelease", back_populates="packages")
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("release_id", "platform", "architecture", "filename", name="uix_app_pkg_platform_arch_filename"),
|
||||
UniqueConstraint(
|
||||
"release_id",
|
||||
"platform",
|
||||
"architecture",
|
||||
"filename",
|
||||
name="uix_app_pkg_platform_arch_filename",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ from sqlalchemy.orm import Mapped, mapped_column
|
||||
from app.models.base import BaseModel
|
||||
|
||||
|
||||
class UserStatus(str, enum.Enum):
|
||||
class UserStatus(enum.StrEnum):
|
||||
"""用户状态"""
|
||||
|
||||
ACTIVE = "active" # 正常
|
||||
@@ -117,6 +117,3 @@ class User(BaseModel):
|
||||
def display_name(self) -> str:
|
||||
"""对外展示的名称"""
|
||||
return self.nickname or f"用户_{self.mobile[-4:]}"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ from app.ai.adapters.base import (
|
||||
TaskStatus,
|
||||
)
|
||||
from app.core.exceptions import PlatformError, PlatformErrorType
|
||||
from app.utils.content_fingerprint import (
|
||||
compute_content_fingerprint,
|
||||
is_vidu_audit_error,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -31,6 +35,10 @@ logger = logging.getLogger(__name__)
|
||||
_TASK_MAPPING_PREFIX = "platform_gateway:task_mapping"
|
||||
_TASK_MAPPING_TTL = 7 * 24 * 60 * 60 # 7 天
|
||||
|
||||
# Redis key 前缀:内容审核失败缓存
|
||||
_AUDIT_REJECTION_PREFIX = "platform_gateway:audit_rejection"
|
||||
_AUDIT_REJECTION_TTL = 24 * 60 * 60 # 24 小时
|
||||
|
||||
|
||||
class PlatformGateway:
|
||||
"""第三方平台统一调用网关"""
|
||||
@@ -61,10 +69,13 @@ class PlatformGateway:
|
||||
redis = self._get_redis()
|
||||
# 正向映射:internal → platform
|
||||
key = self._task_mapping_key(internal_task_id)
|
||||
await redis.hset(key, mapping={
|
||||
"platform": platform,
|
||||
"platform_task_id": platform_task_id,
|
||||
})
|
||||
await redis.hset(
|
||||
key,
|
||||
mapping={
|
||||
"platform": platform,
|
||||
"platform_task_id": platform_task_id,
|
||||
},
|
||||
)
|
||||
await redis.expire(key, _TASK_MAPPING_TTL)
|
||||
# 反向映射:platform → internal(供回调查找)
|
||||
reverse_key = f"{_TASK_MAPPING_PREFIX}:reverse:{platform}:{platform_task_id}"
|
||||
@@ -82,6 +93,33 @@ class PlatformGateway:
|
||||
"platform_task_id": data.get("platform_task_id", ""),
|
||||
}
|
||||
|
||||
def _audit_rejection_key(self, fingerprint: str) -> str:
|
||||
return f"{_AUDIT_REJECTION_PREFIX}:{fingerprint}"
|
||||
|
||||
async def _get_audit_rejection(self, fingerprint: str) -> str | None:
|
||||
"""查询该内容指纹是否近期审核失败。
|
||||
|
||||
Returns:
|
||||
失败错误码(如 "TaskPromptPolicyViolation"),未命中返回 None
|
||||
"""
|
||||
if not fingerprint:
|
||||
return None
|
||||
try:
|
||||
redis = self._get_redis()
|
||||
key = self._audit_rejection_key(fingerprint)
|
||||
return await redis.get(key)
|
||||
except Exception as e:
|
||||
logger.warning(f"[PlatformGateway] 查询审核缓存失败: {e}")
|
||||
return None
|
||||
|
||||
async def _set_audit_rejection(self, fingerprint: str, error_code: str) -> None:
|
||||
"""缓存审核失败结果。"""
|
||||
if not fingerprint or not error_code:
|
||||
return
|
||||
redis = self._get_redis()
|
||||
key = self._audit_rejection_key(fingerprint)
|
||||
await redis.setex(key, _AUDIT_REJECTION_TTL, error_code)
|
||||
|
||||
async def get_internal_task_id_by_platform_task_id(
|
||||
self, platform: str, platform_task_id: str
|
||||
) -> str | None:
|
||||
@@ -156,15 +194,62 @@ class PlatformGateway:
|
||||
若提供,则直接使用该 ID 建立映射;否则自动生成。
|
||||
callback 场景必须传入,确保回调能反查到正确的 Registry 记录。
|
||||
"""
|
||||
internal_task_id = internal_task_id or uuid.uuid4().hex
|
||||
|
||||
# 1. 同一 internal_task_id 已提交过,直接返回(幂等)
|
||||
existing = await self._get_task_mapping(internal_task_id)
|
||||
if existing:
|
||||
return internal_task_id
|
||||
|
||||
# 2. Vidu 内容指纹防重:相同内容近期审核失败则直接拦截
|
||||
fingerprint: str | None = None
|
||||
if platform == "vidu":
|
||||
fingerprint = compute_content_fingerprint(
|
||||
task_type=task_type,
|
||||
video_url=payload.get("video_url"),
|
||||
audio_url=payload.get("audio_url"),
|
||||
ref_photo_url=payload.get("ref_photo_url"),
|
||||
text=payload.get("text"),
|
||||
voice_id=payload.get("voice_id"),
|
||||
)
|
||||
rejected_code = await self._get_audit_rejection(fingerprint)
|
||||
if rejected_code:
|
||||
raise PlatformError(
|
||||
"人物分镜台词未通过安全审核,请修改后重试",
|
||||
platform=platform,
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.CONTENT_VIOLATION,
|
||||
raw_code=rejected_code,
|
||||
)
|
||||
|
||||
# 3. 调用平台 Adapter 提交任务
|
||||
adapter = self._get_task_adapter(platform, task_type)
|
||||
result = await adapter.submit(task_type, payload, callback_url)
|
||||
try:
|
||||
result = await adapter.submit(task_type, payload, callback_url)
|
||||
except PlatformError as e:
|
||||
# Vidu 审核类错误:缓存内容指纹,防止重复调用
|
||||
err_code = e.raw_code
|
||||
if platform == "vidu" and fingerprint and err_code and is_vidu_audit_error(err_code):
|
||||
await self._set_audit_rejection(fingerprint, err_code)
|
||||
raise PlatformError(
|
||||
"人物分镜台词未通过安全审核,请修改后重试",
|
||||
platform=platform,
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.CONTENT_VIOLATION,
|
||||
raw_code=err_code,
|
||||
) from e
|
||||
raise
|
||||
|
||||
if not result.success:
|
||||
raw_code = result.error_code
|
||||
if platform == "vidu" and fingerprint and raw_code and is_vidu_audit_error(raw_code):
|
||||
await self._set_audit_rejection(fingerprint, raw_code)
|
||||
raise PlatformError(
|
||||
result.error_message or "任务提交失败",
|
||||
platform=platform,
|
||||
retryable=result.retryable,
|
||||
error_type=PlatformErrorType.UNKNOWN,
|
||||
raw_code=raw_code,
|
||||
)
|
||||
|
||||
platform_task_id = (result.data or {}).get("task_id", "")
|
||||
@@ -175,7 +260,6 @@ class PlatformGateway:
|
||||
retryable=False,
|
||||
error_type=PlatformErrorType.UNKNOWN,
|
||||
)
|
||||
internal_task_id = internal_task_id or uuid.uuid4().hex
|
||||
await self._store_task_mapping(internal_task_id, platform, platform_task_id)
|
||||
logger.info(
|
||||
f"Task submitted: internal={internal_task_id}, "
|
||||
|
||||
@@ -7,6 +7,7 @@ Async Engine 核心调度器
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any
|
||||
|
||||
from app.core.redis_client import get_redis_client
|
||||
@@ -17,6 +18,13 @@ from app.scheduler.slot_manager import SlotManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 各任务类型最大执行时间(秒),超过后自动标记为 failed
|
||||
TASK_TIMEOUT_SECONDS = {
|
||||
"script": 5 * 60,
|
||||
"subtitle": 10 * 60,
|
||||
"video": 30 * 60,
|
||||
}
|
||||
|
||||
|
||||
class AsyncEngine:
|
||||
"""统一异步作业调度引擎"""
|
||||
@@ -46,13 +54,50 @@ class AsyncEngine:
|
||||
logger.debug("Tick: no running tasks")
|
||||
return
|
||||
|
||||
# 2. 按 task_type 分组
|
||||
# 2. 按 task_type 分组,并处理超时任务
|
||||
tasks_by_type: dict[str, list[Any]] = {}
|
||||
timeout_changes: list[StateChange] = []
|
||||
now = datetime.now(UTC)
|
||||
|
||||
for task_id in running_ids:
|
||||
record = await self.registry.get(task_id)
|
||||
if not record:
|
||||
await self.registry.remove_running(task_id)
|
||||
continue
|
||||
|
||||
max_duration = TASK_TIMEOUT_SECONDS.get(record.task_type)
|
||||
is_timeout = (
|
||||
max_duration
|
||||
and record.status == "running"
|
||||
and record.created_at
|
||||
and (now - datetime.fromisoformat(record.created_at)).total_seconds() > max_duration
|
||||
)
|
||||
|
||||
if is_timeout:
|
||||
logger.warning(
|
||||
f"Task timeout: {task_id}, type={record.task_type}, "
|
||||
f"created_at={record.created_at}"
|
||||
)
|
||||
timeout_changes.append(
|
||||
StateChange(task_id=task_id, field_path="status", value="failed")
|
||||
)
|
||||
timeout_changes.append(
|
||||
StateChange(
|
||||
task_id=task_id,
|
||||
field_path="message",
|
||||
value="任务执行超时,请稍后重试",
|
||||
)
|
||||
)
|
||||
timeout_changes.append(
|
||||
StateChange(
|
||||
task_id=task_id,
|
||||
field_path="error",
|
||||
value=f"任务执行超过 {max_duration} 秒",
|
||||
)
|
||||
)
|
||||
await self.registry.remove_running(task_id)
|
||||
continue
|
||||
|
||||
tasks_by_type.setdefault(record.task_type, []).append(record)
|
||||
|
||||
# 3. 并行执行各 Handler 的 tick
|
||||
@@ -63,10 +108,14 @@ class AsyncEngine:
|
||||
]
|
||||
)
|
||||
|
||||
# 4. 收集并应用状态变更
|
||||
# 4. 收集并应用状态变更(包含超时任务)
|
||||
all_changes: list[StateChange] = []
|
||||
for changes in results:
|
||||
if changes:
|
||||
await self._apply_changes(changes)
|
||||
all_changes.extend(changes)
|
||||
all_changes.extend(timeout_changes)
|
||||
if all_changes:
|
||||
await self._apply_changes(all_changes)
|
||||
|
||||
# 5. 清理已结束的作业
|
||||
await self._cleanup_finished()
|
||||
|
||||
@@ -10,6 +10,7 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from app.ai.prompts.loader import _load_system_meta
|
||||
from app.core.exceptions import InsufficientPointsException
|
||||
from app.core.platform_config import get_platform_config_loader
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.scheduler.handlers.base import AsyncHandler
|
||||
@@ -38,6 +39,7 @@ def _get_category_name(category: str, filename: str) -> str:
|
||||
return f"{cat_name} · {label}"
|
||||
return cat_name
|
||||
|
||||
|
||||
SLOT_KEY = "script:slots"
|
||||
|
||||
|
||||
@@ -64,9 +66,7 @@ class ScriptHandler(AsyncHandler):
|
||||
|
||||
def _get_service(self) -> ScriptService:
|
||||
if self.service is None:
|
||||
raise RuntimeError(
|
||||
"ScriptHandler 需要通过构造函数传入 ScriptService 实例"
|
||||
)
|
||||
raise RuntimeError("ScriptHandler 需要通过构造函数传入 ScriptService 实例")
|
||||
return self.service
|
||||
|
||||
async def tick(
|
||||
@@ -83,7 +83,9 @@ class ScriptHandler(AsyncHandler):
|
||||
changes.extend(await self._process_task(task, registry, slots))
|
||||
except Exception as e:
|
||||
logger.exception(f"[Script {task.task_id}] failed")
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="status", value="failed"))
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="error", value=str(e)[:500])
|
||||
)
|
||||
@@ -129,30 +131,66 @@ class ScriptHandler(AsyncHandler):
|
||||
"shot_count": len(shots),
|
||||
}
|
||||
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="status", value="completed"))
|
||||
# 生成成功后再扣费
|
||||
user_id = params.get("user_id")
|
||||
required_points = params.get("required_points", 0)
|
||||
if user_id and required_points > 0:
|
||||
try:
|
||||
async with AsyncSessionLocal() as db:
|
||||
await ps.consume(
|
||||
db,
|
||||
user_id=user_id,
|
||||
points=required_points,
|
||||
source_type="script",
|
||||
source_id=task.task_id,
|
||||
description="【脚本生成】",
|
||||
)
|
||||
await db.commit()
|
||||
except InsufficientPointsException:
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="message",
|
||||
value="积分不足",
|
||||
)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="error_code",
|
||||
value="insufficient_points",
|
||||
)
|
||||
)
|
||||
return changes
|
||||
except Exception as e:
|
||||
logger.error(f"[ScriptTask {task.task_id}] 扣费失败: {e}")
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="message",
|
||||
value="扣费失败",
|
||||
)
|
||||
)
|
||||
return changes
|
||||
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="completed")
|
||||
)
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="progress", value=100))
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="message", value="脚本生成完成")
|
||||
)
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="completed", value=1))
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="total", value=1))
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="result", value=result_data))
|
||||
|
||||
# 后置扣费(独立 session,失败不影响任务结果)
|
||||
try:
|
||||
async with AsyncSessionLocal() as db:
|
||||
points = ps._calculate_cost("script")
|
||||
await ps.consume(
|
||||
db,
|
||||
user_id=task.user_id,
|
||||
points=points,
|
||||
source_type="script",
|
||||
source_id=task.task_id,
|
||||
description="【脚本生成】",
|
||||
)
|
||||
await db.commit()
|
||||
except Exception as e:
|
||||
logger.error(f"[Script {task.task_id}] 扣费失败: {e}")
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="result", value=result_data)
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception(f"[ScriptTask {task.task_id}] Failed")
|
||||
@@ -160,6 +198,8 @@ class ScriptHandler(AsyncHandler):
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="message", value=str(exc)[:200])
|
||||
)
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="error", value=str(exc)[:500]))
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="error", value=str(exc)[:500])
|
||||
)
|
||||
|
||||
return changes
|
||||
|
||||
@@ -45,9 +45,7 @@ class SubtitleHandler(AsyncHandler):
|
||||
|
||||
def _get_service(self) -> VolcengineCaptionService:
|
||||
if self.service is None:
|
||||
raise RuntimeError(
|
||||
"SubtitleHandler 需要通过构造函数传入 VolcengineCaptionService 实例"
|
||||
)
|
||||
raise RuntimeError("SubtitleHandler 需要通过构造函数传入 VolcengineCaptionService 实例")
|
||||
return self.service
|
||||
|
||||
async def tick(
|
||||
@@ -93,7 +91,9 @@ class SubtitleHandler(AsyncHandler):
|
||||
"utterances": utterances,
|
||||
}
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="completed")
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="status", value="completed"
|
||||
)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="progress", value=100)
|
||||
@@ -106,9 +106,13 @@ class SubtitleHandler(AsyncHandler):
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="completed", value=1)
|
||||
)
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="total", value=1))
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="result", value=result_payload)
|
||||
StateChange(task_id=task.task_id, field_path="total", value=1)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="result", value=result_payload
|
||||
)
|
||||
)
|
||||
elif status.state == "failed":
|
||||
changes.append(
|
||||
@@ -173,9 +177,13 @@ class SubtitleHandler(AsyncHandler):
|
||||
if not volc_task_id:
|
||||
raise ValueError("未返回任务ID")
|
||||
params["volc_task_id"] = volc_task_id
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="params", value=params))
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="message", value="字幕任务已提交")
|
||||
StateChange(task_id=task.task_id, field_path="params", value=params)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="message", value="字幕任务已提交"
|
||||
)
|
||||
)
|
||||
except RuntimeError:
|
||||
logger.error(f"[Subtitle {task.task_id}] service not initialized")
|
||||
|
||||
@@ -9,17 +9,27 @@ Video 任务处理器
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from app.core.exceptions import PlatformError, PlatformErrorType
|
||||
from app.core.platform_config import get_platform_config_loader
|
||||
from app.core.redis_client import get_redis_client
|
||||
from app.scheduler.handlers.base import AsyncHandler
|
||||
from app.scheduler.models import StateChange
|
||||
from app.scheduler.registry import TaskRegistry
|
||||
from app.scheduler.slot_manager import SlotManager
|
||||
from app.services.vidu_service import ViduService
|
||||
from app.utils.content_fingerprint import (
|
||||
compute_content_fingerprint,
|
||||
extract_vidu_error_code,
|
||||
is_vidu_audit_error,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SLOT_KEY = "vidu:video_slots"
|
||||
|
||||
_AUDIT_REJECTION_PREFIX = "platform_gateway:audit_rejection"
|
||||
_AUDIT_REJECTION_TTL = 24 * 60 * 60 # 24 小时
|
||||
|
||||
|
||||
def _get_video_max_slots() -> int:
|
||||
"""从 platform-config.yaml 读取 rate_limit 配置作为 max_slots"""
|
||||
@@ -45,11 +55,39 @@ class VideoHandler(AsyncHandler):
|
||||
|
||||
def _get_service(self) -> ViduService:
|
||||
if self.service is None:
|
||||
raise RuntimeError(
|
||||
"VideoHandler 需要通过构造函数传入 ViduService 实例"
|
||||
)
|
||||
raise RuntimeError("VideoHandler 需要通过构造函数传入 ViduService 实例")
|
||||
return self.service
|
||||
|
||||
async def _cache_audit_rejection_if_needed(
|
||||
self, params: dict[str, Any], error_message: str | None
|
||||
) -> None:
|
||||
"""如果失败原因是 Vidu 审核类错误,缓存内容指纹防止重复提交。"""
|
||||
err_code = extract_vidu_error_code(error_message)
|
||||
if not err_code or not is_vidu_audit_error(err_code):
|
||||
return
|
||||
|
||||
fingerprint = compute_content_fingerprint(
|
||||
task_type="lip_sync",
|
||||
video_url=params.get("video_url"),
|
||||
audio_url=params.get("audio_url"),
|
||||
ref_photo_url=params.get("ref_photo_url"),
|
||||
text=params.get("text"),
|
||||
voice_id=params.get("voice_id"),
|
||||
)
|
||||
if not fingerprint:
|
||||
return
|
||||
|
||||
try:
|
||||
redis = get_redis_client()
|
||||
key = f"{_AUDIT_REJECTION_PREFIX}:{fingerprint}"
|
||||
await redis.setex(key, _AUDIT_REJECTION_TTL, err_code)
|
||||
logger.info(
|
||||
f"[Video] 审核失败内容已缓存: fingerprint={fingerprint[:16]}..., "
|
||||
f"err_code={err_code}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"[Video] 缓存审核失败结果出错: {e}")
|
||||
|
||||
async def tick(
|
||||
self, tasks: list[Any], registry: TaskRegistry, slots: SlotManager
|
||||
) -> list[StateChange]:
|
||||
@@ -87,11 +125,7 @@ class VideoHandler(AsyncHandler):
|
||||
value=1,
|
||||
)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="total", value=1
|
||||
)
|
||||
)
|
||||
changes.append(StateChange(task_id=task.task_id, field_path="total", value=1))
|
||||
elif task.status == "failed":
|
||||
# callback 已标记失败,移除 running
|
||||
await registry.remove_running(task.task_id)
|
||||
@@ -150,6 +184,15 @@ class VideoHandler(AsyncHandler):
|
||||
f"video_url={video_url[:60]}..."
|
||||
)
|
||||
elif vidu_state == "failed":
|
||||
error_message = vidu_status.get("message") or "视频生成失败"
|
||||
err_code = extract_vidu_error_code(error_message)
|
||||
is_audit = err_code and is_vidu_audit_error(err_code)
|
||||
message = (
|
||||
"人物分镜台词未通过安全审核,请修改后重试"
|
||||
if is_audit
|
||||
else "视频生成失败"
|
||||
)
|
||||
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
@@ -161,20 +204,29 @@ class VideoHandler(AsyncHandler):
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="message",
|
||||
value="视频生成失败",
|
||||
value=message,
|
||||
)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="error",
|
||||
value=vidu_status.get("message") or "视频生成失败",
|
||||
value=error_message,
|
||||
)
|
||||
)
|
||||
if is_audit:
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="error_code",
|
||||
value="content_violation",
|
||||
)
|
||||
)
|
||||
await self._cache_audit_rejection_if_needed(params, error_message)
|
||||
await registry.remove_running(task.task_id)
|
||||
logger.warning(
|
||||
f"[Video {task.task_id}] 主动查询 Vidu 任务失败: "
|
||||
f"{vidu_status.get('message')}"
|
||||
f"{error_message}"
|
||||
)
|
||||
else:
|
||||
# 仍在处理中,继续等待
|
||||
@@ -182,15 +234,11 @@ class VideoHandler(AsyncHandler):
|
||||
f"[Video {task.task_id}] 主动查询 Vidu 状态: {vidu_state},继续等待"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"[Video {task.task_id}] 主动查询 Vidu 失败: {e}"
|
||||
)
|
||||
logger.warning(f"[Video {task.task_id}] 主动查询 Vidu 失败: {e}")
|
||||
continue # ← 已提交,不再重复提交
|
||||
|
||||
# 提交阶段:占用 slot,提交成功后自动释放
|
||||
async with slots.acquire_ctx(
|
||||
SLOT_KEY, task.task_id, self.max_slots
|
||||
) as acquired:
|
||||
async with slots.acquire_ctx(SLOT_KEY, task.task_id, self.max_slots) as acquired:
|
||||
if not acquired:
|
||||
continue
|
||||
|
||||
@@ -227,9 +275,7 @@ class VideoHandler(AsyncHandler):
|
||||
raise ValueError("未返回任务ID")
|
||||
params["vidu_task_id"] = vidu_task_id
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="params", value=params
|
||||
)
|
||||
StateChange(task_id=task.task_id, field_path="params", value=params)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
@@ -241,9 +287,7 @@ class VideoHandler(AsyncHandler):
|
||||
except RuntimeError:
|
||||
logger.error(f"[Video {task.task_id}] service not initialized")
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="status", value="failed"
|
||||
)
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
@@ -259,12 +303,50 @@ class VideoHandler(AsyncHandler):
|
||||
value="视频处理服务未就绪",
|
||||
)
|
||||
)
|
||||
except PlatformError as e:
|
||||
error_message = str(e)
|
||||
is_audit = e.error_type == PlatformErrorType.CONTENT_VIOLATION
|
||||
if is_audit:
|
||||
message = "人物分镜台词未通过安全审核,请修改后重试"
|
||||
elif e.error_type == PlatformErrorType.AUTH_FAILED:
|
||||
message = "视频服务认证失败,请联系客服"
|
||||
elif e.error_type == PlatformErrorType.RATE_LIMIT:
|
||||
message = "视频生成服务繁忙,请稍后重试"
|
||||
else:
|
||||
message = "视频生成任务提交失败,请稍后重试"
|
||||
|
||||
logger.error(f"[Video {task.task_id}] submit platform error: {e}")
|
||||
changes.append(
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="message",
|
||||
value=message,
|
||||
)
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="error",
|
||||
value=error_message,
|
||||
)
|
||||
)
|
||||
if is_audit:
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id,
|
||||
field_path="error_code",
|
||||
value="content_violation",
|
||||
)
|
||||
)
|
||||
# 审核类错误在 PlatformGateway 已写缓存,此处幂等补充
|
||||
await self._cache_audit_rejection_if_needed(params, error_message)
|
||||
except Exception as e:
|
||||
logger.error(f"[Video {task.task_id}] submit error: {e}")
|
||||
changes.append(
|
||||
StateChange(
|
||||
task_id=task.task_id, field_path="status", value="failed"
|
||||
)
|
||||
StateChange(task_id=task.task_id, field_path="status", value="failed")
|
||||
)
|
||||
changes.append(
|
||||
StateChange(
|
||||
|
||||
@@ -24,6 +24,7 @@ class TaskRecord:
|
||||
total: int = 0
|
||||
result: dict[str, Any] = field(default_factory=dict)
|
||||
error: str | None = None
|
||||
error_code: str | None = None
|
||||
params: dict[str, Any] | Any = field(default_factory=dict)
|
||||
created_at: str = ""
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
import json
|
||||
import logging
|
||||
from collections.abc import Awaitable
|
||||
from datetime import UTC
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
from redis.asyncio import Redis
|
||||
|
||||
@@ -54,8 +55,8 @@ class TaskRegistry:
|
||||
if params:
|
||||
data["params"] = json.dumps(params, ensure_ascii=False)
|
||||
|
||||
await self.redis.hset(_task_key(task_id), mapping=data)
|
||||
await self.redis.expire(_task_key(task_id), ttl)
|
||||
await cast(Awaitable[int], self.redis.hset(_task_key(task_id), mapping=data))
|
||||
await cast(Awaitable[int], self.redis.expire(_task_key(task_id), ttl))
|
||||
logger.debug(f"Registry created: {task_id}, type={task_type}")
|
||||
|
||||
async def update(self, task_id: str, **fields: Any) -> None:
|
||||
@@ -68,12 +69,12 @@ class TaskRegistry:
|
||||
mapping[key] = ""
|
||||
else:
|
||||
mapping[key] = str(value)
|
||||
await self.redis.hset(_task_key(task_id), mapping=mapping)
|
||||
await cast(Awaitable[int], self.redis.hset(_task_key(task_id), mapping=mapping))
|
||||
logger.debug(f"Registry updated: {task_id}, fields={list(fields.keys())}")
|
||||
|
||||
async def get(self, task_id: str) -> TaskRecord | None:
|
||||
"""读取完整作业记录"""
|
||||
data = await self.redis.hgetall(_task_key(task_id))
|
||||
data = await cast(Awaitable[dict[Any, Any]], self.redis.hgetall(_task_key(task_id)))
|
||||
if not data:
|
||||
return None
|
||||
|
||||
@@ -88,6 +89,8 @@ class TaskRegistry:
|
||||
return int(raw)
|
||||
except ValueError:
|
||||
return 0
|
||||
if key in ("error_code", "error") and raw == "":
|
||||
return None
|
||||
return raw
|
||||
|
||||
parsed = {k: _parse(k, v) for k, v in data.items()}
|
||||
@@ -107,21 +110,22 @@ class TaskRegistry:
|
||||
total=parsed.get("total", 0),
|
||||
result=parsed.get("result", {}),
|
||||
error=parsed.get("error"),
|
||||
error_code=parsed.get("error_code"),
|
||||
params=params,
|
||||
created_at=parsed.get("created_at", ""),
|
||||
)
|
||||
|
||||
async def add_running(self, task_id: str) -> None:
|
||||
"""将作业标记为 running(加入全局 running 集合)"""
|
||||
await self.redis.sadd(KEY_RUNNING_SET, task_id)
|
||||
await cast(Awaitable[int], self.redis.sadd(KEY_RUNNING_SET, task_id))
|
||||
|
||||
async def remove_running(self, task_id: str) -> None:
|
||||
"""将作业从全局 running 集合移除"""
|
||||
await self.redis.srem(KEY_RUNNING_SET, task_id)
|
||||
await cast(Awaitable[int], self.redis.srem(KEY_RUNNING_SET, task_id))
|
||||
|
||||
async def get_running_task_ids(self) -> list[str]:
|
||||
"""获取所有 running 的作业 ID 列表"""
|
||||
members = await self.redis.smembers(KEY_RUNNING_SET)
|
||||
members = await cast(Awaitable[set[Any]], self.redis.smembers(KEY_RUNNING_SET))
|
||||
return list(members)
|
||||
|
||||
async def list_running_by_user(self, user_id: str) -> list[TaskRecord]:
|
||||
@@ -139,5 +143,5 @@ class TaskRegistry:
|
||||
|
||||
async def delete(self, task_id: str) -> None:
|
||||
"""删除作业记录"""
|
||||
await self.redis.delete(_task_key(task_id))
|
||||
await self.redis.srem(KEY_RUNNING_SET, task_id)
|
||||
await cast(Awaitable[int], self.redis.delete(_task_key(task_id)))
|
||||
await cast(Awaitable[int], self.redis.srem(KEY_RUNNING_SET, task_id))
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
from collections.abc import Awaitable
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import cast
|
||||
|
||||
from redis.asyncio import Redis
|
||||
|
||||
@@ -37,7 +39,9 @@ class SlotManager:
|
||||
async def acquire(self, slot_key: str, slot_id: str, max_slots: int) -> bool:
|
||||
"""申请一个槽位。返回 True 表示成功,False 表示槽位已满。"""
|
||||
try:
|
||||
result = await self.redis.eval(_ACQUIRE_LUA, 1, slot_key, slot_id, str(max_slots))
|
||||
result = await cast(
|
||||
Awaitable[str], self.redis.eval(_ACQUIRE_LUA, 1, slot_key, slot_id, str(max_slots))
|
||||
)
|
||||
acquired = result == 1
|
||||
if acquired:
|
||||
logger.debug(f"Slot acquired: {slot_key}/{slot_id} (max={max_slots})")
|
||||
@@ -51,7 +55,7 @@ class SlotManager:
|
||||
async def release(self, slot_key: str, slot_id: str) -> None:
|
||||
"""释放一个槽位。"""
|
||||
try:
|
||||
await self.redis.srem(slot_key, slot_id)
|
||||
await cast(Awaitable[int], self.redis.srem(slot_key, slot_id))
|
||||
logger.debug(f"Slot released: {slot_key}/{slot_id}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Slot release error: {slot_key}/{slot_id}: {e}")
|
||||
@@ -78,6 +82,6 @@ class SlotManager:
|
||||
async def count(self, slot_key: str) -> int:
|
||||
"""获取当前已占用的槽位数量。"""
|
||||
try:
|
||||
return await self.redis.scard(slot_key)
|
||||
return await cast(Awaitable[int], self.redis.scard(slot_key))
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
@@ -19,12 +19,38 @@ class MobileLoginRequest(BaseModel):
|
||||
app_version: str | None = Field(None, description="应用版本号")
|
||||
|
||||
|
||||
class PasswordLoginRequest(BaseModel):
|
||||
"""手机号密码登录请求"""
|
||||
|
||||
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
|
||||
password: str = Field(..., description="密码", min_length=6, max_length=128)
|
||||
device_id: str = Field(..., description="设备唯一标识")
|
||||
device_name: str | None = Field(None, description="设备名称")
|
||||
os_info: str | None = Field(None, description="操作系统信息")
|
||||
app_version: str | None = Field(None, description="应用版本号")
|
||||
|
||||
|
||||
class SendSmsCodeRequest(BaseModel):
|
||||
"""发送短信验证码请求"""
|
||||
|
||||
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
|
||||
|
||||
|
||||
class SetPasswordRequest(BaseModel):
|
||||
"""设置/修改密码请求"""
|
||||
|
||||
old_password: str | None = Field(None, description="旧密码(修改时必填)", max_length=128)
|
||||
new_password: str = Field(..., description="新密码", min_length=6, max_length=128)
|
||||
|
||||
|
||||
class ResetPasswordRequest(BaseModel):
|
||||
"""短信验证码重置密码请求"""
|
||||
|
||||
mobile: str = Field(..., description="手机号", min_length=11, max_length=20)
|
||||
code: str = Field(..., description="短信验证码", min_length=4, max_length=10)
|
||||
new_password: str = Field(..., description="新密码", min_length=6, max_length=128)
|
||||
|
||||
|
||||
class RefreshTokenRequest(BaseModel):
|
||||
"""刷新 Token 请求"""
|
||||
|
||||
@@ -39,6 +65,12 @@ class TokenResponse(BaseModel):
|
||||
user: UserInfo = Field(..., description="用户信息")
|
||||
|
||||
|
||||
class CheckPasswordResponse(BaseModel):
|
||||
"""检查是否设置过密码响应"""
|
||||
|
||||
has_password: bool = Field(..., description="是否已设置密码")
|
||||
|
||||
|
||||
class TokenPayload(BaseModel):
|
||||
"""Token 载荷"""
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
==============
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class BgmMusicItem(BaseModel):
|
||||
@@ -18,8 +18,7 @@ class BgmMusicItem(BaseModel):
|
||||
duration: float | None = Field(default=None, description="时长(秒)")
|
||||
sort_order: int = Field(default=0, description="排序权重")
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class BgmMusicListResponse(BaseModel):
|
||||
|
||||
@@ -6,14 +6,12 @@
|
||||
{ code: number; data: T; message: string }
|
||||
"""
|
||||
|
||||
from typing import Any, Generic, TypeVar
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
T = TypeVar("T")
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class ApiResponse(BaseModel, Generic[T]):
|
||||
class ApiResponse[T](BaseModel):
|
||||
"""
|
||||
统一 API 响应格式
|
||||
|
||||
@@ -27,17 +25,18 @@ class ApiResponse(BaseModel, Generic[T]):
|
||||
data: T | None = Field(default=None, description="响应数据")
|
||||
message: str = Field(default="success", description="提示信息")
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"example": {
|
||||
"code": 200,
|
||||
"data": {},
|
||||
"message": "success",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class PaginatedData(BaseModel, Generic[T]):
|
||||
class PaginatedData[T](BaseModel):
|
||||
"""分页数据包装"""
|
||||
|
||||
items: list[T] = Field(description="数据列表")
|
||||
@@ -61,18 +60,23 @@ class PaginationParams(BaseModel):
|
||||
class ApiErrorResponse(BaseModel):
|
||||
"""错误响应格式"""
|
||||
|
||||
code: int = Field(description="错误码")
|
||||
code: int = Field(description="HTTP 状态码")
|
||||
message: str = Field(description="错误信息")
|
||||
error_code: str | None = Field(default=None, description="应用级错误码")
|
||||
detail: dict[str, Any] | None = Field(default=None, description="详细错误信息")
|
||||
|
||||
|
||||
def success_response(data: T | None = None, message: str = "success") -> ApiResponse[T]:
|
||||
def success_response[T](data: T | None = None, message: str = "success") -> ApiResponse[T]:
|
||||
"""构造成功响应"""
|
||||
return ApiResponse(code=200, data=data, message=message)
|
||||
|
||||
|
||||
def error_response(
|
||||
code: int, message: str, detail: dict[str, Any] | None = None
|
||||
code: int,
|
||||
message: str,
|
||||
detail: dict[str, Any] | None = None,
|
||||
*,
|
||||
error_code: str | None = None,
|
||||
) -> ApiErrorResponse:
|
||||
"""构造错误响应"""
|
||||
return ApiErrorResponse(code=code, message=message, detail=detail)
|
||||
return ApiErrorResponse(code=code, message=message, error_code=error_code, detail=detail)
|
||||
|
||||
@@ -25,6 +25,3 @@ class SegmentStatus(StrEnum):
|
||||
PROCESSING = "processing"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ class MatchMaterialRequest(BaseModel):
|
||||
|
||||
scene: str = Field(description="分镜场景描述")
|
||||
duration: float = Field(description="所需时长(秒)", gt=0)
|
||||
project_id: str | None = Field(
|
||||
default=None, description="项目ID,用于跨分镜去重"
|
||||
)
|
||||
project_id: str | None = Field(default=None, description="项目ID,用于跨分镜去重")
|
||||
|
||||
@field_validator("scene")
|
||||
@classmethod
|
||||
@@ -56,9 +54,7 @@ class BatchMatchSceneItem(BaseModel):
|
||||
class BatchMatchMaterialRequest(BaseModel):
|
||||
"""批量匹配素材请求"""
|
||||
|
||||
project_id: str | None = Field(
|
||||
default=None, description="项目ID,用于跨分镜去重"
|
||||
)
|
||||
project_id: str | None = Field(default=None, description="项目ID,用于跨分镜去重")
|
||||
scenes: list[BatchMatchSceneItem] = Field(
|
||||
description="分镜场景列表",
|
||||
min_length=1,
|
||||
@@ -76,6 +72,4 @@ class BatchMatchMaterialResponse(BaseModel):
|
||||
"""批量匹配素材响应"""
|
||||
|
||||
project_id: str | None = Field(description="项目ID")
|
||||
results: list[MaterialInfo | None] = Field(
|
||||
description="匹配结果列表,与 scenes 一一对应"
|
||||
)
|
||||
results: list[MaterialInfo | None] = Field(description="匹配结果列表,与 scenes 一一对应")
|
||||
|
||||
@@ -9,6 +9,7 @@ from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
# ── 余额查询 ──────────────────────────────────────────
|
||||
|
||||
|
||||
class PointBalanceResponse(BaseModel):
|
||||
"""积分余额响应"""
|
||||
|
||||
@@ -20,6 +21,7 @@ class PointBalanceResponse(BaseModel):
|
||||
|
||||
# ── 流水记录 ──────────────────────────────────────────
|
||||
|
||||
|
||||
class PointTransactionItem(BaseModel):
|
||||
"""单条流水记录"""
|
||||
|
||||
@@ -33,7 +35,10 @@ class PointTransactionItem(BaseModel):
|
||||
source_type: str | None = Field(None, description="消费来源类型")
|
||||
source_id: str | None = Field(None, description="消费来源业务 ID")
|
||||
duration: float | None = Field(None, description="时长(秒),按秒计费业务记录")
|
||||
category: str | None = Field(None, description="业务分类:脚本生成 / 配音合成 / 视频生成 / 压制成片 / 字幕烧录 / 封面设计 / 充值")
|
||||
category: str | None = Field(
|
||||
None,
|
||||
description="业务分类:脚本生成 / 配音合成 / 视频生成 / 压制成片 / 字幕烧录 / 封面设计 / 充值",
|
||||
)
|
||||
description: str | None = None
|
||||
created_at: datetime
|
||||
|
||||
@@ -49,6 +54,7 @@ class PointTransactionListResponse(BaseModel):
|
||||
|
||||
# ── 充值 ──────────────────────────────────────────────
|
||||
|
||||
|
||||
class RechargeRequest(BaseModel):
|
||||
"""充值请求"""
|
||||
|
||||
@@ -70,6 +76,7 @@ class RechargeResponse(BaseModel):
|
||||
|
||||
# ── 积分预估 ──────────────────────────────────────────
|
||||
|
||||
|
||||
class CostEstimateResponse(BaseModel):
|
||||
"""积分预估响应"""
|
||||
|
||||
@@ -80,6 +87,7 @@ class CostEstimateResponse(BaseModel):
|
||||
|
||||
# ── 充值订单 ──────────────────────────────────────────
|
||||
|
||||
|
||||
class RechargeOrderItem(BaseModel):
|
||||
"""充值订单记录"""
|
||||
|
||||
@@ -104,11 +112,16 @@ class RechargeOrderListResponse(BaseModel):
|
||||
|
||||
# ── 消费扣费 ──────────────────────────────────────────
|
||||
|
||||
|
||||
class ConsumeRequest(BaseModel):
|
||||
"""消费扣费请求(供前端/Rust 层调用)"""
|
||||
|
||||
points: int = Field(gt=0, description="消耗积分数量")
|
||||
source_type: str = Field(description="消费来源类型,如 compose / subtitle_burn / cover_design / video")
|
||||
source_type: str = Field(
|
||||
description="消费来源类型,如 compose / subtitle_burn / cover_design / video"
|
||||
)
|
||||
source_id: str = Field(description="消费来源业务 ID")
|
||||
description: str | None = Field(default=None, description="消费描述")
|
||||
allow_negative: bool = Field(default=False, description="是否允许扣费后余额为负(不确定消耗场景用)")
|
||||
allow_negative: bool = Field(
|
||||
default=False, description="是否允许扣费后余额为负(不确定消耗场景用)"
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
===============
|
||||
"""
|
||||
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.schemas.segment import Segment
|
||||
@@ -93,7 +92,9 @@ class GenerateTitleRequest(BaseModel):
|
||||
script_content: str = Field(..., description="脚本内容(utterances 文本拼接)", min_length=1)
|
||||
title_type: str = Field(..., description="标题类型:main(大标题) / sub(小标题)")
|
||||
max_length: int = Field(default=8, ge=1, le=100, description="最大字数限制")
|
||||
usage: str = Field(default="video", description="使用场景:video(视频画面标题) / cover(封面标题)")
|
||||
usage: str = Field(
|
||||
default="video", description="使用场景:video(视频画面标题) / cover(封面标题)"
|
||||
)
|
||||
|
||||
|
||||
class GenerateTitleResponse(BaseModel):
|
||||
|
||||
@@ -32,9 +32,7 @@ class Segment(BaseModel):
|
||||
duration: int | None = Field(default=None, description="时长(秒)")
|
||||
voice_id: str | None = Field(default=None, description="音色ID(空镜时使用)")
|
||||
status: SegmentStatus = Field(default=SegmentStatus.PENDING)
|
||||
provider_task_id: str | None = Field(
|
||||
default=None, description="供应商任务ID"
|
||||
)
|
||||
provider_task_id: str | None = Field(default=None, description="供应商任务ID")
|
||||
video_url: str | None = Field(default=None, description="生成后的视频URL")
|
||||
local_path: str | None = Field(default=None, description="本地视频路径")
|
||||
qiniu_url: str | None = Field(default=None, description="七牛云URL")
|
||||
|
||||
@@ -6,7 +6,6 @@ Tauri updater 插件所需的请求/响应模型。
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
@@ -58,6 +57,7 @@ class ReleaseListItem(BaseModel):
|
||||
# Tauri updater 插件所需的 JSON 格式
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
|
||||
class TauriPlatformInfo(BaseModel):
|
||||
"""Tauri updater 单平台信息"""
|
||||
|
||||
@@ -73,7 +73,7 @@ class TauriUpdateResponse(BaseModel):
|
||||
|
||||
version: str = Field(..., description="新版本号")
|
||||
notes: str = Field(default="", description="更新说明")
|
||||
pub_date: Optional[str] = Field(default=None, description="发布时间(RFC 3339)")
|
||||
pub_date: str | None = Field(default=None, description="发布时间(RFC 3339)")
|
||||
mandatory: bool = Field(default=False, description="是否强制更新(自定义扩展字段)")
|
||||
platforms: dict[str, TauriPlatformInfo] = Field(
|
||||
..., description="平台安装包映射,key 格式:OS-ARCH"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class UserInfo(BaseModel):
|
||||
@@ -30,8 +30,7 @@ class UserProfileResponse(BaseModel):
|
||||
last_login_at: datetime | None = Field(None, description="最后登录时间")
|
||||
created_at: datetime = Field(..., description="注册时间")
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class UpdateNicknameRequest(BaseModel):
|
||||
|
||||
@@ -220,7 +220,10 @@ def validate_and_normalize_shots(raw_data: Any) -> list[dict[str, Any]]:
|
||||
duration = item.get("duration")
|
||||
duration_str = parse_duration(duration) # 返回如 "5s"
|
||||
try:
|
||||
normalized["duration"] = int(re.search(r"\d+", duration_str).group())
|
||||
match = re.search(r"\d+", duration_str)
|
||||
if match is None:
|
||||
raise ValueError("时长字符串中未找到数字")
|
||||
normalized["duration"] = int(match.group())
|
||||
except (AttributeError, ValueError):
|
||||
normalized["duration"] = 5
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import hashlib
|
||||
import logging
|
||||
import random
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
import httpx
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -32,9 +33,9 @@ from app.models.user_device import UserDevice
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# ── 短信业务常量(数值类配置不走 .env,内嵌代码)─────
|
||||
SMS_CODE_LENGTH = 6 # 验证码位数
|
||||
SMS_CODE_EXPIRE_MINUTES = 5 # 验证码有效期(分钟)
|
||||
SMS_DAILY_LIMIT = 10 # 单手机号每日发送上限
|
||||
SMS_CODE_LENGTH = 6 # 验证码位数
|
||||
SMS_CODE_EXPIRE_MINUTES = 5 # 验证码有效期(分钟)
|
||||
SMS_DAILY_LIMIT = 10 # 单手机号每日发送上限
|
||||
|
||||
# ========== SSE 连接池 ==========
|
||||
# key: user_id, value: asyncio.Queue(用于向该用户的 SSE 连接发送消息)
|
||||
@@ -73,6 +74,7 @@ async def _kick_old_device(user_id: str) -> None:
|
||||
|
||||
# ========== 验证码校验 ==========
|
||||
|
||||
|
||||
async def verify_sms_code(mobile: str, code: str) -> bool:
|
||||
"""
|
||||
校验短信验证码。
|
||||
@@ -145,9 +147,7 @@ async def send_sms_code(mobile: str) -> str:
|
||||
)
|
||||
else:
|
||||
# 配置不完整,记录警告但不打印验证码
|
||||
logger.warning(
|
||||
f"[SMS] B2M 短信配置不完整,验证码未发送: 手机号={mobile}"
|
||||
)
|
||||
logger.warning(f"[SMS] B2M 短信配置不完整,验证码未发送: 手机号={mobile}")
|
||||
except SMSError as e:
|
||||
logger.error(f"[SMS] 短信发送失败: {e}")
|
||||
# 短信发送失败不影响验证码生成
|
||||
@@ -159,6 +159,7 @@ async def send_sms_code(mobile: str) -> str:
|
||||
|
||||
# ========== Token 工具 ==========
|
||||
|
||||
|
||||
def _hash_refresh_token(token: str) -> str:
|
||||
"""Refresh Token SHA256 哈希(用于数据库存储)"""
|
||||
return hashlib.sha256(token.encode()).hexdigest()
|
||||
@@ -166,6 +167,7 @@ def _hash_refresh_token(token: str) -> str:
|
||||
|
||||
# ========== 登录服务 ==========
|
||||
|
||||
|
||||
async def login_with_sms(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -260,9 +262,7 @@ async def refresh_access_token(
|
||||
refresh_token_hash = _hash_refresh_token(refresh_token)
|
||||
|
||||
# 2. 查设备记录
|
||||
device = await device_crud.get_by_refresh_token_hash(
|
||||
db, refresh_token_hash=refresh_token_hash
|
||||
)
|
||||
device = await device_crud.get_by_refresh_token_hash(db, refresh_token_hash=refresh_token_hash)
|
||||
if device is None:
|
||||
raise ValueError("设备已失效,请重新登录")
|
||||
|
||||
@@ -288,7 +288,116 @@ async def refresh_access_token(
|
||||
}
|
||||
|
||||
|
||||
async def logout(db: AsyncSession, *, user_id: str) -> bool:
|
||||
async def login_with_password(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
mobile: str,
|
||||
password: str,
|
||||
device_id: str,
|
||||
device_name: str | None = None,
|
||||
os_info: str | None = None,
|
||||
app_version: str | None = None,
|
||||
ip: str | None = None,
|
||||
source: str = "mobile_password",
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
手机号密码登录。
|
||||
|
||||
流程:
|
||||
1. 查询用户
|
||||
2. 校验密码
|
||||
3. 更新登录信息
|
||||
4. 踢掉旧设备(SSE 推送)
|
||||
5. 创建/覆盖设备记录
|
||||
6. 签发双 Token
|
||||
"""
|
||||
from app.core.security import verify_password
|
||||
|
||||
# 1. 查询用户
|
||||
user = await user_crud.get_by_mobile(db, mobile=mobile)
|
||||
if user is None:
|
||||
raise ValueError("用户不存在")
|
||||
|
||||
# 2. 校验密码
|
||||
if not user.password_hash:
|
||||
raise ValueError("该账号未设置密码,请使用验证码登录")
|
||||
|
||||
if not verify_password(password, user.password_hash):
|
||||
raise ValueError("密码错误")
|
||||
|
||||
# 检查用户状态
|
||||
if not user.is_active:
|
||||
raise ValueError("账号已被封禁,请联系客服")
|
||||
|
||||
# 3. 更新登录信息
|
||||
await user_crud.update_login_info(db, user_id=user.id, ip=ip)
|
||||
|
||||
# 4. 踢掉旧设备(SSE 推送)
|
||||
await _kick_old_device(str(user.id))
|
||||
|
||||
# 5. 签发双 Token
|
||||
access_token = create_access_token(data={"sub": str(user.id)})
|
||||
refresh_token = create_refresh_token(data={"sub": str(user.id)})
|
||||
refresh_token_hash = _hash_refresh_token(refresh_token)
|
||||
|
||||
# 6. 创建/覆盖设备记录
|
||||
await device_crud.create_or_update(
|
||||
db,
|
||||
user_id=user.id,
|
||||
device_id=device_id,
|
||||
device_name=device_name,
|
||||
os_info=os_info,
|
||||
app_version=app_version,
|
||||
refresh_token_hash=refresh_token_hash,
|
||||
)
|
||||
|
||||
return {
|
||||
"access_token": access_token,
|
||||
"refresh_token": refresh_token,
|
||||
"user": {
|
||||
"id": user.id,
|
||||
"mobile": user.mobile,
|
||||
"nickname": user.nickname or "",
|
||||
"avatar": user.avatar_url or "",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def reset_password_with_sms(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
mobile: str,
|
||||
code: str,
|
||||
new_password: str,
|
||||
) -> bool:
|
||||
"""
|
||||
短信验证码重置密码。
|
||||
|
||||
流程:
|
||||
1. 校验验证码
|
||||
2. 查询用户
|
||||
3. 更新密码哈希
|
||||
"""
|
||||
from app.core.security import hash_password
|
||||
|
||||
settings = get_settings()
|
||||
|
||||
# 1. 校验验证码(白名单内的手机号跳过校验)
|
||||
if mobile not in settings.sms_code_whitelist_set and not await verify_sms_code(mobile, code):
|
||||
raise ValueError("验证码错误或已过期")
|
||||
|
||||
# 2. 查询用户
|
||||
user = await user_crud.get_by_mobile(db, mobile=mobile)
|
||||
if user is None:
|
||||
raise ValueError("用户不存在")
|
||||
|
||||
# 3. 更新密码
|
||||
new_hash = hash_password(new_password)
|
||||
await user_crud.update_password(db, user_id=user.id, password_hash=new_hash)
|
||||
return True
|
||||
|
||||
|
||||
async def logout(db: AsyncSession, *, user_id: UUID | str) -> bool:
|
||||
"""
|
||||
用户登出。
|
||||
|
||||
@@ -297,14 +406,14 @@ async def logout(db: AsyncSession, *, user_id: str) -> bool:
|
||||
2. 注销 SSE 连接
|
||||
"""
|
||||
await device_crud.delete_by_user_id(db, user_id=user_id)
|
||||
unregister_sse_connection(user_id)
|
||||
unregister_sse_connection(str(user_id))
|
||||
return True
|
||||
|
||||
|
||||
async def get_current_user_device(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: str,
|
||||
user_id: UUID | str,
|
||||
) -> UserDevice | None:
|
||||
"""获取当前用户的设备记录"""
|
||||
return await device_crud.get_by_user_id(db, user_id=user_id)
|
||||
|
||||
@@ -9,6 +9,8 @@ import logging
|
||||
import math
|
||||
import random
|
||||
import re
|
||||
from collections.abc import Awaitable
|
||||
from typing import Any, cast
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -16,6 +18,7 @@ from app.core.exceptions import ValidationException
|
||||
from app.core.redis_client import get_redis_client
|
||||
from app.crud import broll_category, broll_material
|
||||
from app.models.broll_category import BrollCategory
|
||||
from app.models.broll_material import BrollMaterial
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -26,10 +29,15 @@ _USED_MATERIALS_TTL = 7 * 24 * 3600
|
||||
def _normalize_scene(scene: str) -> str:
|
||||
"""标准化场景描述,用于匹配三级分类 name"""
|
||||
# 去除所有 Unicode 空白字符(空格、全角空格、换行、tab 等)
|
||||
return re.sub(r"\s+", "", scene)
|
||||
cleaned = re.sub(r"\s+", "", scene)
|
||||
# 去除常见中文标点符号(逗号、句号、感叹号、问号、顿号、分号、冒号、引号、括号等)
|
||||
cleaned = re.sub(r"[,。!?、;:" "''()【】《》]+", "", cleaned)
|
||||
# 去除零宽字符(零宽空格、零宽非连接符、零宽连接符、零宽非断空格等)
|
||||
cleaned = re.sub(r"[\u200b-\u200f\ufeff]+", "", cleaned)
|
||||
return cleaned
|
||||
|
||||
|
||||
def _weighted_choice(materials: list) -> object: # noqa: ANN001
|
||||
def _weighted_choice(materials: list[BrollMaterial]) -> BrollMaterial:
|
||||
"""
|
||||
加权随机选择素材
|
||||
|
||||
@@ -45,9 +53,9 @@ def _weighted_choice(materials: list) -> object: # noqa: ANN001
|
||||
total_weight = sum(weights)
|
||||
|
||||
if total_weight == 0:
|
||||
return random.choice(materials)
|
||||
return random.choice(materials) # nosec B311 素材抽样,非加密场景
|
||||
|
||||
r = random.uniform(0, total_weight)
|
||||
r = random.uniform(0, total_weight) # nosec B311 素材抽样,非加密场景
|
||||
cumulative = 0.0
|
||||
for m, w in zip(materials, weights, strict=True):
|
||||
cumulative += w
|
||||
@@ -69,10 +77,9 @@ async def _try_fallback_to_parent(
|
||||
- 若 scene 含 '-',取后半部分作为 parent_name(如 '电路施工-电路施工' -> '电路施工')
|
||||
- 若不含 '-',直接以整个 scene 作为 parent_name
|
||||
|
||||
匹配策略(逐级降级):
|
||||
匹配策略:
|
||||
1. 精确匹配 level=2 分类 name
|
||||
2. 模糊匹配(LIKE %parent_name%),兼容 "电路施工" → "电路施工镜"
|
||||
3. 去掉常见后缀(镜、阶段等)再精确匹配
|
||||
2. 模糊匹配(LIKE %parent_name%)
|
||||
|
||||
返回:
|
||||
随机选中的一个 level=3 子分类,或 None
|
||||
@@ -83,37 +90,20 @@ async def _try_fallback_to_parent(
|
||||
parent_name = normalized_scene
|
||||
|
||||
# 1. 精确匹配
|
||||
parent = await broll_category.get_by_name_and_level(
|
||||
db, name=parent_name, level=2
|
||||
)
|
||||
parent = await broll_category.get_by_name_and_level(db, name=parent_name, level=2)
|
||||
|
||||
# 2. 模糊匹配(兼容 "电路施工" → "电路施工镜")
|
||||
# 2. 模糊匹配
|
||||
if parent is None:
|
||||
parent = await broll_category.get_by_name_like_and_level(
|
||||
db, name=parent_name, level=2
|
||||
)
|
||||
|
||||
# 3. 去掉常见后缀再试
|
||||
if parent is None:
|
||||
for suffix in ("镜", "阶段"):
|
||||
if not parent_name.endswith(suffix):
|
||||
candidate = parent_name + suffix
|
||||
parent = await broll_category.get_by_name_and_level(
|
||||
db, name=candidate, level=2
|
||||
)
|
||||
if parent:
|
||||
break
|
||||
parent = await broll_category.get_by_name_like_and_level(db, name=parent_name, level=2)
|
||||
|
||||
if parent is None:
|
||||
return None
|
||||
|
||||
children = await broll_category.get_children_by_parent_id(
|
||||
db, parent_id=parent.id, level=3
|
||||
)
|
||||
children = await broll_category.get_children_by_parent_id(db, parent_id=parent.id, level=3)
|
||||
if not children:
|
||||
return None
|
||||
|
||||
return random.choice(children)
|
||||
return random.choice(children) # nosec B311 素材抽样,非加密场景
|
||||
|
||||
|
||||
async def match_material(
|
||||
@@ -155,40 +145,49 @@ async def match_material(
|
||||
|
||||
normalized = _normalize_scene(scene)
|
||||
|
||||
# 1. 查找三级分类(精确匹配 + 顺序颠倒兜底)
|
||||
category = await broll_category.get_by_name_and_level(
|
||||
db, name=normalized, level=3
|
||||
)
|
||||
# 若精确匹配失败,尝试将 "A-B" 倒序为 "B-A" 再匹配
|
||||
# 1. 查找三级分类(精确匹配 -> 全量内存匹配兜底 -> 顺序颠倒 -> 上级回退)
|
||||
category = await broll_category.get_by_name_and_level(db, name=normalized, level=3)
|
||||
# 精确匹配失败时,全量查询后在内存标准化匹配(兼容数据库 name 含不可见字符)
|
||||
if category is None:
|
||||
all_categories = await broll_category.get_by_level(db, level=3)
|
||||
for c in all_categories:
|
||||
if _normalize_scene(c.name) == normalized:
|
||||
category = c
|
||||
logger.info(f"素材分类全量内存匹配命中: '{normalized}' -> '{c.name}'")
|
||||
break
|
||||
# 若仍失败,尝试将 "A-B" 倒序为 "B-A" 再匹配
|
||||
if category is None:
|
||||
parts = normalized.rsplit("-", 1)
|
||||
if len(parts) == 2:
|
||||
reversed_name = f"{parts[1]}-{parts[0]}"
|
||||
category = await broll_category.get_by_name_and_level(
|
||||
db, name=reversed_name, level=3
|
||||
)
|
||||
category = await broll_category.get_by_name_and_level(db, name=reversed_name, level=3)
|
||||
if category:
|
||||
logger.info(
|
||||
f"素材分类顺序颠倒兜底命中: '{normalized}' -> '{reversed_name}'"
|
||||
)
|
||||
logger.info(f"素材分类顺序颠倒兜底命中: '{normalized}' -> '{reversed_name}'")
|
||||
# 若仍失败,回退到上级分类随机选取
|
||||
if category is None:
|
||||
category = await _try_fallback_to_parent(db, normalized)
|
||||
if category:
|
||||
logger.info(
|
||||
f"素材回退到上级分类命中: '{normalized}' -> '{category.name}'"
|
||||
)
|
||||
logger.info(f"素材回退到上级分类命中: '{normalized}' -> '{category.name}'")
|
||||
if category is None:
|
||||
logger.debug(f"未找到分类: {normalized}")
|
||||
logger.warning(f"素材匹配失败: 未找到分类 '{normalized}' (原始 scene: '{scene}')")
|
||||
return None
|
||||
|
||||
# 2. 查询候选素材
|
||||
materials = await broll_material.get_active_by_category_and_duration(
|
||||
db, category_id=category.id, min_duration=required_duration
|
||||
)
|
||||
# 2. 查询该分类下所有 active 素材(先不过滤时长,用于日志诊断)
|
||||
all_materials = await broll_material.get_active_by_categories(db, category_ids=[category.id])
|
||||
if not all_materials:
|
||||
logger.warning(f"素材匹配失败: 分类 '{normalized}' 下无任何可用素材")
|
||||
return None
|
||||
|
||||
# 按时长过滤(优先严格匹配,失败时逐步放宽到 70% 兜底)
|
||||
materials = [m for m in all_materials if m.duration >= required_duration]
|
||||
if not materials:
|
||||
logger.debug(
|
||||
f"分类 {normalized} 无足够时长的素材 (需 >= {required_duration}s)"
|
||||
materials = [m for m in all_materials if m.duration >= required_duration * 0.7]
|
||||
if not materials:
|
||||
materials = all_materials
|
||||
if not materials:
|
||||
max_duration = max(m.duration for m in all_materials)
|
||||
logger.warning(
|
||||
f"素材匹配失败: 分类 '{normalized}' 无足够时长的素材 (需 >= {required_duration}s, 最大可用: {max_duration}s)"
|
||||
)
|
||||
return None
|
||||
|
||||
@@ -198,7 +197,7 @@ async def match_material(
|
||||
try:
|
||||
redis = get_redis_client()
|
||||
key = f"proj:{project_id}:used_materials"
|
||||
used_urls = set(await redis.smembers(key))
|
||||
used_urls = set(await cast(Awaitable[set[Any]], redis.smembers(key)))
|
||||
except Exception as e:
|
||||
logger.warning(f"Redis 去重查询失败,降级为不去重: {e}")
|
||||
|
||||
@@ -217,8 +216,8 @@ async def match_material(
|
||||
try:
|
||||
redis = get_redis_client()
|
||||
key = f"proj:{project_id}:used_materials"
|
||||
await redis.sadd(key, chosen.url)
|
||||
await redis.expire(key, _USED_MATERIALS_TTL)
|
||||
await cast(Awaitable[int], redis.sadd(key, chosen.url))
|
||||
await cast(Awaitable[int], redis.expire(key, _USED_MATERIALS_TTL))
|
||||
except Exception as e:
|
||||
logger.warning(f"Redis 去重记录失败: {e}")
|
||||
|
||||
@@ -255,35 +254,36 @@ async def batch_match(
|
||||
normalized_scenes = [_normalize_scene(s["scene"]) for s in scenes]
|
||||
unique_names = list(set(normalized_scenes))
|
||||
|
||||
# 2. 批量查询分类(1 次 DB)—— 同时查询原始名和倒序名
|
||||
reversed_names: list[str] = []
|
||||
name_to_reversed: dict[str, str] = {}
|
||||
# 2. 批量查询分类:优先精确查询,失败时全量内存匹配兜底
|
||||
categories = await broll_category.get_by_names_and_level(db, names=unique_names, level=3)
|
||||
category_map: dict[str, BrollCategory] = {}
|
||||
for c in categories:
|
||||
category_map[_normalize_scene(c.name)] = c
|
||||
|
||||
# 收集未命中的 name,准备全量兜底
|
||||
unmatched_by_exact = [name for name in unique_names if name not in category_map]
|
||||
if unmatched_by_exact:
|
||||
all_categories = await broll_category.get_by_level(db, level=3)
|
||||
for c in all_categories:
|
||||
normalized_db_name = _normalize_scene(c.name)
|
||||
if normalized_db_name not in category_map:
|
||||
category_map[normalized_db_name] = c
|
||||
|
||||
# 构建原始 scene -> category 的映射
|
||||
reversed_map: dict[str, str] = {}
|
||||
for name in unique_names:
|
||||
parts = name.rsplit("-", 1)
|
||||
if len(parts) == 2:
|
||||
rev = f"{parts[1]}-{parts[0]}"
|
||||
reversed_names.append(rev)
|
||||
name_to_reversed[name] = rev
|
||||
reversed_map[name] = f"{parts[1]}-{parts[0]}"
|
||||
|
||||
all_query_names = unique_names + reversed_names
|
||||
categories = await broll_category.get_by_names_and_level(
|
||||
db, names=all_query_names, level=3
|
||||
)
|
||||
category_map: dict[str, object] = {}
|
||||
for c in categories:
|
||||
category_map[c.name] = c
|
||||
|
||||
# 构建原始 scene -> category 的映射(优先精确匹配,fallback 倒序匹配)
|
||||
scene_to_category: dict[str, object] = {}
|
||||
scene_to_category: dict[str, BrollCategory] = {}
|
||||
for name in unique_names:
|
||||
if name in category_map:
|
||||
scene_to_category[name] = category_map[name]
|
||||
elif name in name_to_reversed and name_to_reversed[name] in category_map:
|
||||
rev = name_to_reversed[name]
|
||||
elif name in reversed_map and reversed_map[name] in category_map:
|
||||
rev = reversed_map[name]
|
||||
scene_to_category[name] = category_map[rev]
|
||||
logger.info(
|
||||
f"批量匹配顺序颠倒兜底命中: '{name}' -> '{rev}'"
|
||||
)
|
||||
logger.info(f"批量匹配顺序颠倒兜底命中: '{name}' -> '{rev}'")
|
||||
|
||||
# 3. 未匹配的 scene 回退到上级分类随机选取
|
||||
unmatched = [name for name in unique_names if name not in scene_to_category]
|
||||
@@ -291,15 +291,11 @@ async def batch_match(
|
||||
fallback_cat = await _try_fallback_to_parent(db, name)
|
||||
if fallback_cat:
|
||||
scene_to_category[name] = fallback_cat
|
||||
logger.info(
|
||||
f"批量匹配回退到上级分类命中: '{name}' -> '{fallback_cat.name}'"
|
||||
)
|
||||
logger.info(f"批量匹配回退到上级分类命中: '{name}' -> '{fallback_cat.name}'")
|
||||
|
||||
# 4. 收集所有需要的 category_id
|
||||
needed_category_ids = [
|
||||
scene_to_category[name].id
|
||||
for name in unique_names
|
||||
if name in scene_to_category
|
||||
scene_to_category[name].id for name in unique_names if name in scene_to_category
|
||||
]
|
||||
|
||||
# 4. 批量查询素材(1 次 DB)
|
||||
@@ -308,7 +304,7 @@ async def batch_match(
|
||||
)
|
||||
|
||||
# 按 category_id 分组,方便内存过滤
|
||||
materials_by_category: dict[int, list] = {}
|
||||
materials_by_category: dict[int, list[BrollMaterial]] = {}
|
||||
for m in all_materials:
|
||||
materials_by_category.setdefault(m.category_id, []).append(m)
|
||||
|
||||
@@ -318,26 +314,38 @@ async def batch_match(
|
||||
try:
|
||||
redis = get_redis_client()
|
||||
key = f"proj:{project_id}:used_materials"
|
||||
used_urls = set(await redis.smembers(key))
|
||||
used_urls = set(await cast(Awaitable[set[Any]], redis.smembers(key)))
|
||||
except Exception as e:
|
||||
logger.warning(f"Redis 去重查询失败,降级为不去重: {e}")
|
||||
|
||||
# 6. 内存中逐个匹配
|
||||
results: list[dict | None] = []
|
||||
chosen_materials: list = [] # 记录选中的素材,用于批量更新
|
||||
chosen_materials: list[BrollMaterial] = [] # 记录选中的素材,用于批量更新
|
||||
|
||||
for idx, scene_name in enumerate(normalized_scenes):
|
||||
required_duration = scenes[idx]["duration"]
|
||||
|
||||
category = scene_to_category.get(scene_name)
|
||||
if category is None:
|
||||
original_scene = scenes[idx]["scene"]
|
||||
logger.warning(
|
||||
f"批量素材匹配失败: 未找到分类 '{scene_name}' (原始 scene: '{original_scene}')"
|
||||
)
|
||||
results.append(None)
|
||||
continue
|
||||
|
||||
materials = materials_by_category.get(category.id, [])
|
||||
# 按时长过滤
|
||||
# 按时长过滤(优先严格匹配,失败时逐步放宽到 70% 兜底)
|
||||
candidates = [m for m in materials if m.duration >= required_duration]
|
||||
if not candidates:
|
||||
candidates = [m for m in materials if m.duration >= required_duration * 0.7]
|
||||
if not candidates:
|
||||
candidates = materials
|
||||
if not candidates:
|
||||
max_duration = max((m.duration for m in materials), default=0)
|
||||
logger.warning(
|
||||
f"批量素材匹配失败: 分类 '{scene_name}' -> '{category.name}' 无足够时长的素材 (需 >= {required_duration}s, 最大可用: {max_duration}s)"
|
||||
)
|
||||
results.append(None)
|
||||
continue
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import logging
|
||||
import math
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import yaml
|
||||
from sqlalchemy import select
|
||||
@@ -33,6 +33,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from app.core.exceptions import InsufficientPointsException
|
||||
from app.models.point_batch import PointBatch
|
||||
from app.models.point_transaction import PointTransaction
|
||||
from app.models.user_point import UserPoint
|
||||
@@ -46,11 +47,11 @@ if TYPE_CHECKING:
|
||||
_CONFIG_PATH = Path(__file__).resolve().parents[2] / "config" / "points-config.yaml"
|
||||
|
||||
|
||||
def _load_points_config() -> dict:
|
||||
def _load_points_config() -> dict[str, Any]:
|
||||
"""加载积分计费配置。服务启动时读取一次,后续内存中使用。"""
|
||||
if not _CONFIG_PATH.exists():
|
||||
raise FileNotFoundError(f"积分配置文件不存在: {_CONFIG_PATH}")
|
||||
with open(_CONFIG_PATH, "r", encoding="utf-8") as f:
|
||||
with open(_CONFIG_PATH, encoding="utf-8") as f:
|
||||
cfg = yaml.safe_load(f) or {}
|
||||
# 合并为统一的查询字典:source_type -> {"mode": "fixed|duration|free", ...}
|
||||
merged: dict[str, dict] = {}
|
||||
@@ -65,18 +66,22 @@ def _load_points_config() -> dict:
|
||||
return merged
|
||||
|
||||
|
||||
POINTS_CONFIG: dict[str, dict] = _load_points_config()
|
||||
POINTS_CONFIG: dict[str, Any] = _load_points_config()
|
||||
|
||||
|
||||
def get_recharge_options() -> list[dict]:
|
||||
"""获取充值档位配置(由后端控制,支持积分赠送)"""
|
||||
return POINTS_CONFIG.get("_recharge_options", [])
|
||||
options = POINTS_CONFIG.get("_recharge_options", [])
|
||||
if isinstance(options, list):
|
||||
return options
|
||||
return []
|
||||
|
||||
|
||||
def get_chargeable_source_types() -> list[str]:
|
||||
"""获取所有需要扣费的业务类型列表(排除免费业务)"""
|
||||
return [
|
||||
key for key, cfg in POINTS_CONFIG.items()
|
||||
key
|
||||
for key, cfg in POINTS_CONFIG.items()
|
||||
if not key.startswith("_") and cfg.get("mode") != "free"
|
||||
]
|
||||
|
||||
@@ -163,11 +168,10 @@ def _estimate_max_cost(source_type: str, param: dict | None = None) -> int:
|
||||
|
||||
# ── 余额查询 ──────────────────────────────────────────
|
||||
|
||||
|
||||
async def get_user_balance(db: AsyncSession, user_id: UUID | str) -> dict:
|
||||
"""获取用户积分余额快照(实时计算,排除已过期批次)。"""
|
||||
result = await db.execute(
|
||||
select(UserPoint).where(UserPoint.user_id == user_id)
|
||||
)
|
||||
result = await db.execute(select(UserPoint).where(UserPoint.user_id == user_id))
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
if not up:
|
||||
@@ -182,8 +186,7 @@ async def get_user_balance(db: AsyncSession, user_id: UUID | str) -> dict:
|
||||
from sqlalchemy import func as _func
|
||||
|
||||
available_result = await db.execute(
|
||||
select(_func.coalesce(_func.sum(PointBatch.remaining), 0))
|
||||
.where(
|
||||
select(_func.coalesce(_func.sum(PointBatch.remaining), 0)).where(
|
||||
PointBatch.user_id == user_id,
|
||||
PointBatch.remaining > 0,
|
||||
PointBatch.expired_at > _now(),
|
||||
@@ -221,6 +224,7 @@ async def check_balance(
|
||||
|
||||
# ── 充值 ──────────────────────────────────────────────
|
||||
|
||||
|
||||
async def recharge(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -247,8 +251,7 @@ async def recharge(
|
||||
# 幂等保护:同一笔订单(order_id)只能充值一次
|
||||
if order_id:
|
||||
existing_result = await db.execute(
|
||||
select(PointTransaction)
|
||||
.where(
|
||||
select(PointTransaction).where(
|
||||
PointTransaction.source_id == str(order_id),
|
||||
PointTransaction.type == "recharge",
|
||||
)
|
||||
@@ -259,9 +262,7 @@ async def recharge(
|
||||
return existing_tx
|
||||
|
||||
# 1. 获取或创建用户积分账户
|
||||
result = await db.execute(
|
||||
select(UserPoint).where(UserPoint.user_id == user_id)
|
||||
)
|
||||
result = await db.execute(select(UserPoint).where(UserPoint.user_id == user_id))
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
if not up:
|
||||
@@ -353,7 +354,7 @@ async def consume(
|
||||
直接扣费(后置计费)。
|
||||
|
||||
业务执行成功后调用,按实际消耗直接扣除余额。
|
||||
默认不允许欠费(余额不足时抛出 ValueError)。
|
||||
默认不允许欠费(余额不足时抛出 InsufficientPointsException)。
|
||||
Scheduler 后置扣费等场景可设置 allow_negative=True,允许余额变负。
|
||||
|
||||
:param points: 实际消耗积分(正整数)
|
||||
@@ -383,9 +384,7 @@ async def consume(
|
||||
|
||||
# 2. 获取用户积分账户(加锁)
|
||||
result = await db.execute(
|
||||
select(UserPoint)
|
||||
.where(UserPoint.user_id == user_id)
|
||||
.with_for_update()
|
||||
select(UserPoint).where(UserPoint.user_id == user_id).with_for_update()
|
||||
)
|
||||
up = result.scalar_one_or_none()
|
||||
|
||||
@@ -404,7 +403,7 @@ async def consume(
|
||||
# 3. 余额检查:用实时可用余额(未过期批次 remaining 总和),避免 expire_batches 延迟导致超扣
|
||||
available = sum(b.remaining for b in batches)
|
||||
if not allow_negative and available < points:
|
||||
raise ValueError(f"积分不足,当前可用余额 {available},需要 {points} 积分")
|
||||
raise InsufficientPointsException(f"积分不足,当前可用余额 {available},需要 {points} 积分")
|
||||
|
||||
remaining_to_deduct = points
|
||||
for batch in batches:
|
||||
@@ -440,6 +439,7 @@ async def consume(
|
||||
|
||||
# ── 过期回收 ──────────────────────────────────────────
|
||||
|
||||
|
||||
async def expire_batches(db: AsyncSession) -> int:
|
||||
"""
|
||||
回收过期积分批次。返回过期积分总数。
|
||||
@@ -468,9 +468,7 @@ async def expire_batches(db: AsyncSession) -> int:
|
||||
|
||||
# 获取用户积分账户(加锁)
|
||||
up_result = await db.execute(
|
||||
select(UserPoint)
|
||||
.where(UserPoint.user_id == batch.user_id)
|
||||
.with_for_update()
|
||||
select(UserPoint).where(UserPoint.user_id == batch.user_id).with_for_update()
|
||||
)
|
||||
up = up_result.scalar_one_or_none()
|
||||
if not up:
|
||||
|
||||
@@ -104,7 +104,9 @@ class QiniuService:
|
||||
# 项目前缀
|
||||
PROJECT_PREFIX = "meijiaka-zy"
|
||||
|
||||
def generate_key(self, file_type: str, original_filename: str, user_id: str = None) -> str:
|
||||
def generate_key(
|
||||
self, file_type: str, original_filename: str, user_id: str | None = None
|
||||
) -> str:
|
||||
"""
|
||||
生成规范的文件存储路径
|
||||
|
||||
@@ -143,7 +145,7 @@ class QiniuService:
|
||||
return mime_type in allowed_types
|
||||
|
||||
def get_upload_token(
|
||||
self, bucket: str, key: str, expires: int = 3600, policy: dict = None
|
||||
self, bucket: str, key: str, expires: int = 3600, policy: dict | None = None
|
||||
) -> str:
|
||||
"""
|
||||
生成上传凭证(客户端直传使用)
|
||||
@@ -197,9 +199,9 @@ class QiniuService:
|
||||
def upload_file(
|
||||
self,
|
||||
local_path: str,
|
||||
key: str = None,
|
||||
key: str | None = None,
|
||||
file_type: str = "audio",
|
||||
user_id: str = None,
|
||||
user_id: str | None = None,
|
||||
check_duplicate: bool = True,
|
||||
) -> dict:
|
||||
"""
|
||||
@@ -222,15 +224,15 @@ class QiniuService:
|
||||
"is_duplicate": 是否复用已有文件
|
||||
}
|
||||
"""
|
||||
local_path = Path(local_path)
|
||||
if not local_path.exists():
|
||||
raise FileNotFoundError(f"文件不存在: {local_path}")
|
||||
local_path_obj = Path(local_path)
|
||||
if not local_path_obj.exists():
|
||||
raise FileNotFoundError(f"文件不存在: {local_path_obj}")
|
||||
|
||||
# 根据文件类型获取对应的 bucket 和 domain
|
||||
bucket, domain = self._get_bucket_and_domain(file_type)
|
||||
|
||||
# 计算文件 MD5 哈希
|
||||
file_md5 = self._calculate_file_hash(local_path)
|
||||
file_md5 = self._calculate_file_hash(local_path_obj)
|
||||
|
||||
# 检查是否已存在相同文件
|
||||
if check_duplicate:
|
||||
@@ -248,20 +250,20 @@ class QiniuService:
|
||||
|
||||
# 自动生成 Key
|
||||
if key is None:
|
||||
key = self.generate_key(file_type, local_path.name, user_id)
|
||||
key = self.generate_key(file_type, local_path_obj.name, user_id)
|
||||
|
||||
# 生成上传 Token
|
||||
token = self.get_upload_token(bucket, key)
|
||||
|
||||
# 使用分片上传
|
||||
ret, info = put_file(up_token=token, key=key, file_path=str(local_path))
|
||||
ret, info = put_file(up_token=token, key=key, file_path=str(local_path_obj))
|
||||
|
||||
if ret is None:
|
||||
raise Exception(f"上传失败: {info}")
|
||||
|
||||
# 获取文件信息
|
||||
mime_type, _ = mimetypes.guess_type(str(local_path))
|
||||
fsize = local_path.stat().st_size
|
||||
mime_type, _ = mimetypes.guess_type(str(local_path_obj))
|
||||
fsize = local_path_obj.stat().st_size
|
||||
|
||||
return {
|
||||
"key": ret["key"],
|
||||
@@ -277,8 +279,8 @@ class QiniuService:
|
||||
stream: BinaryIO,
|
||||
key: str,
|
||||
mime_type: str = "application/octet-stream",
|
||||
bucket: str = None,
|
||||
domain: str = None,
|
||||
bucket: str | None = None,
|
||||
domain: str | None = None,
|
||||
) -> dict:
|
||||
"""
|
||||
上传文件流到七牛云
|
||||
@@ -317,7 +319,9 @@ class QiniuService:
|
||||
|
||||
return {"key": ret["key"], "hash": ret["hash"], "url": self.get_file_url(domain, key)}
|
||||
|
||||
def upload_audio(self, local_path: str, user_id: str = None, key: str = None) -> dict:
|
||||
def upload_audio(
|
||||
self, local_path: str, user_id: str | None = None, key: str | None = None
|
||||
) -> dict:
|
||||
"""
|
||||
上传音频文件(专用接口)
|
||||
|
||||
@@ -336,7 +340,9 @@ class QiniuService:
|
||||
|
||||
return self.upload_file(local_path=local_path, key=key, file_type="audio", user_id=user_id)
|
||||
|
||||
def upload_video(self, local_path: str, user_id: str = None, key: str = None) -> dict:
|
||||
def upload_video(
|
||||
self, local_path: str, user_id: str | None = None, key: str | None = None
|
||||
) -> dict:
|
||||
"""
|
||||
上传视频文件(专用接口)
|
||||
|
||||
@@ -454,9 +460,9 @@ class QiniuService:
|
||||
async def upload_file_async(
|
||||
self,
|
||||
local_path: str,
|
||||
key: str = None,
|
||||
key: str | None = None,
|
||||
file_type: str = "audio",
|
||||
user_id: str = None,
|
||||
user_id: str | None = None,
|
||||
check_duplicate: bool = True,
|
||||
) -> dict:
|
||||
"""异步版本 upload_file"""
|
||||
@@ -469,19 +475,21 @@ class QiniuService:
|
||||
stream: BinaryIO,
|
||||
key: str,
|
||||
mime_type: str = "application/octet-stream",
|
||||
bucket: str = None,
|
||||
domain: str = None,
|
||||
bucket: str | None = None,
|
||||
domain: str | None = None,
|
||||
) -> dict:
|
||||
"""异步版本 upload_stream"""
|
||||
return await asyncio.to_thread(
|
||||
self.upload_stream, stream, key, mime_type, bucket, domain
|
||||
)
|
||||
return await asyncio.to_thread(self.upload_stream, stream, key, mime_type, bucket, domain)
|
||||
|
||||
async def upload_audio_async(self, local_path: str, user_id: str = None, key: str = None) -> dict:
|
||||
async def upload_audio_async(
|
||||
self, local_path: str, user_id: str | None = None, key: str | None = None
|
||||
) -> dict:
|
||||
"""异步版本 upload_audio"""
|
||||
return await asyncio.to_thread(self.upload_audio, local_path, user_id, key)
|
||||
|
||||
async def upload_video_async(self, local_path: str, user_id: str = None, key: str = None) -> dict:
|
||||
async def upload_video_async(
|
||||
self, local_path: str, user_id: str | None = None, key: str | None = None
|
||||
) -> dict:
|
||||
"""异步版本 upload_video"""
|
||||
return await asyncio.to_thread(self.upload_video, local_path, user_id, key)
|
||||
|
||||
|
||||
@@ -7,9 +7,16 @@ import asyncio
|
||||
import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from app.ai.model_router import get_model_router
|
||||
from app.ai.prompts import load_prompt_file, load_script_user_prompt
|
||||
from app.core.exceptions import (
|
||||
AIEmptyResponseException,
|
||||
AIParseErrorException,
|
||||
AITimeoutException,
|
||||
PromptNotFoundException,
|
||||
)
|
||||
from app.schemas.script import ScriptShot
|
||||
from app.services.ai_response_utils import (
|
||||
safe_parse_ai_json_response,
|
||||
@@ -22,12 +29,9 @@ logger = logging.getLogger(__name__)
|
||||
class ScriptService:
|
||||
"""脚本生成服务"""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.prompts_dir = Path(__file__).parent.parent / "ai" / "prompts"
|
||||
|
||||
|
||||
|
||||
def _load_prompt(self, name: str) -> str:
|
||||
"""加载 Prompt 模板"""
|
||||
prompt_file = self.prompts_dir / f"{name}.txt"
|
||||
@@ -58,7 +62,7 @@ class ScriptService:
|
||||
# 加载 Prompt
|
||||
system_prompt = load_prompt_file(category, filename)
|
||||
if not system_prompt:
|
||||
raise ValueError(f"未找到提示词: category={category}, filename={filename}")
|
||||
raise PromptNotFoundException(f"未找到提示词: category={category}, filename={filename}")
|
||||
|
||||
# 用户提示词
|
||||
user_prompt = load_script_user_prompt(
|
||||
@@ -75,24 +79,26 @@ class ScriptService:
|
||||
)
|
||||
|
||||
if not result.content or not result.content.strip():
|
||||
raise ValueError("AI 返回内容为空,请检查模型配置或重试")
|
||||
raise AIEmptyResponseException("AI 返回内容为空,请检查模型配置或重试")
|
||||
|
||||
success, parsed_data, error_msg = safe_parse_ai_json_response(result.content)
|
||||
|
||||
if not success:
|
||||
raise ValueError(error_msg or "AI 返回格式错误,无法解析为 JSON")
|
||||
raise AIParseErrorException(error_msg or "AI 返回格式错误,无法解析为 JSON")
|
||||
|
||||
try:
|
||||
shots_data = validate_and_normalize_shots(parsed_data)
|
||||
|
||||
if not shots_data:
|
||||
raise ValueError("AI 返回的分镜数据为空或格式不正确")
|
||||
raise AIEmptyResponseException("AI 返回的分镜数据为空或格式不正确")
|
||||
|
||||
shots = [ScriptShot(**shot) for shot in shots_data]
|
||||
return shots
|
||||
|
||||
except (AIEmptyResponseException, AIParseErrorException):
|
||||
raise
|
||||
except Exception as e:
|
||||
raise ValueError(f"分镜数据处理失败: {str(e)}")
|
||||
raise AIParseErrorException(f"分镜数据处理失败: {str(e)}")
|
||||
|
||||
async def polish_content(
|
||||
self,
|
||||
@@ -144,21 +150,23 @@ class ScriptService:
|
||||
)
|
||||
return result.content.strip()
|
||||
except TimeoutError:
|
||||
raise ValueError("润色请求超时,请重试")
|
||||
raise AITimeoutException("润色请求超时,请重试")
|
||||
except (AIEmptyResponseException, AIParseErrorException, AITimeoutException):
|
||||
raise
|
||||
except Exception as e:
|
||||
raise ValueError(f"润色失败: {str(e)}")
|
||||
raise AIParseErrorException(f"润色失败: {str(e)}")
|
||||
|
||||
async def check_model_health(self) -> dict:
|
||||
"""检查模型健康状态"""
|
||||
model_router = await get_model_router()
|
||||
health_results = await model_router.health_check()
|
||||
|
||||
models = []
|
||||
models: list[dict[str, Any]] = []
|
||||
available_count = 0
|
||||
recommended = None
|
||||
recommended: dict[str, Any] | None = None
|
||||
|
||||
for _provider_id, health in health_results.items():
|
||||
model_info = {
|
||||
model_info: dict[str, Any] = {
|
||||
"id": health.id,
|
||||
"name": health.name,
|
||||
"is_available": health.is_available,
|
||||
@@ -169,9 +177,12 @@ class ScriptService:
|
||||
|
||||
if health.is_available:
|
||||
available_count += 1
|
||||
if recommended is None or health.response_time < recommended.get(
|
||||
"response_time", float("inf")
|
||||
):
|
||||
current_best = (
|
||||
float("inf")
|
||||
if recommended is None
|
||||
else float(recommended.get("response_time") or float("inf"))
|
||||
)
|
||||
if health.response_time < current_best:
|
||||
recommended = model_info
|
||||
|
||||
total = len(models)
|
||||
@@ -188,7 +199,6 @@ class ScriptService:
|
||||
"""测试指定模型连接"""
|
||||
model_router = await get_model_router()
|
||||
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
try:
|
||||
|
||||
@@ -76,9 +76,7 @@ class B2MSMSService:
|
||||
if self.secret_key:
|
||||
key_bytes = self.secret_key.encode("utf-8")
|
||||
if len(key_bytes) not in (16, 24, 32):
|
||||
raise SMSError(
|
||||
f"AES 密钥长度必须是 16/24/32 字节,当前 {len(key_bytes)} 字节"
|
||||
)
|
||||
raise SMSError(f"AES 密钥长度必须是 16/24/32 字节,当前 {len(key_bytes)} 字节")
|
||||
self._secret_key_bytes = key_bytes
|
||||
|
||||
if not all([self.app_id, self.secret_key, self.base_url]):
|
||||
@@ -245,6 +243,7 @@ class B2MSMSService:
|
||||
|
||||
# ── 便捷函数 ──────────────────────────────────────────
|
||||
|
||||
|
||||
def get_sms_service() -> B2MSMSService:
|
||||
"""获取短信服务实例"""
|
||||
return B2MSMSService()
|
||||
|
||||
@@ -207,8 +207,9 @@ class ViduService:
|
||||
error_type=PlatformErrorType.BAD_REQUEST,
|
||||
)
|
||||
|
||||
logger.info(f"[Vidu Clone] 复刻成功: voice_id={result.data.get('voice_id')}")
|
||||
return result.data or {}
|
||||
clone_data = result.data or {}
|
||||
logger.info(f"[Vidu Clone] 复刻成功: voice_id={clone_data.get('voice_id')}")
|
||||
return clone_data
|
||||
|
||||
async def query_clone_task(self, voice_id: str) -> dict[str, Any]:
|
||||
"""Vidu 声音复刻是同步接口,无独立查询。
|
||||
@@ -270,6 +271,8 @@ class ViduService:
|
||||
result_data = status.result or {}
|
||||
return {
|
||||
"state": ViduAdapter.denormalize_state(status.state),
|
||||
"creations": [{"url": result_data.get("video_url")}] if result_data.get("video_url") else [],
|
||||
"creations": (
|
||||
[{"url": result_data.get("video_url")}] if result_data.get("video_url") else []
|
||||
),
|
||||
"message": status.error_message,
|
||||
}
|
||||
|
||||
@@ -155,10 +155,7 @@ class VolcengineCaptionService:
|
||||
error_type=PlatformErrorType.BAD_REQUEST,
|
||||
)
|
||||
|
||||
logger.warning(
|
||||
f"{task_name}超过最大轮询次数: task_id={task_id}, "
|
||||
f"retries={retries}"
|
||||
)
|
||||
logger.warning(f"{task_name}超过最大轮询次数: task_id={task_id}, " f"retries={retries}")
|
||||
raise PlatformError(
|
||||
f"{task_name}超时,请稍后重试",
|
||||
platform="volcengine_caption",
|
||||
|
||||
@@ -78,9 +78,7 @@ class VolcengineMediakitService:
|
||||
)
|
||||
|
||||
if not response.success:
|
||||
raise RuntimeError(
|
||||
response.error_message or "抠图失败"
|
||||
)
|
||||
raise RuntimeError(response.error_message or "抠图失败")
|
||||
|
||||
result_image_url = (response.data or {}).get("image_url", "")
|
||||
return RemoveBackgroundResult(
|
||||
|
||||
@@ -69,7 +69,9 @@ class WechatPayService:
|
||||
self.notify_url = settings.WXPAY_NOTIFY_URL
|
||||
|
||||
if not all([self.mchid, self.appid, self.api_key]):
|
||||
raise WechatPayError("微信支付配置不完整:WXPAY_MCHID / WXPAY_APPID / WXPAY_API_KEY 未配置")
|
||||
raise WechatPayError(
|
||||
"微信支付配置不完整:WXPAY_MCHID / WXPAY_APPID / WXPAY_API_KEY 未配置"
|
||||
)
|
||||
|
||||
# ── 签名与验签 ──────────────────────────────────────
|
||||
|
||||
@@ -85,7 +87,9 @@ class WechatPayService:
|
||||
5. MD5 加密,结果转大写
|
||||
"""
|
||||
# 过滤空值和 sign
|
||||
filtered = {k: str(v) for k, v in params.items() if v is not None and v != "" and k != "sign"}
|
||||
filtered = {
|
||||
k: str(v) for k, v in params.items() if v is not None and v != "" and k != "sign"
|
||||
}
|
||||
# ASCII 升序排序
|
||||
sorted_items = sorted(filtered.items(), key=lambda x: x[0])
|
||||
# 拼接字符串
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user