Files
fastmovieai/fastmovie-admin/plugin/shortplay/app/api/controller/GenerateController.php
T
李建琦 eae151fd57 FastMovieAI AI短剧创作平台 二开基线
- 源码: xhadmincn/FastMovieAI (Apache 2.0)
- 二开: Docker部署, Swoole改Select, route.php修复, 补update/VERSION
- vendor/示例资源已gitignore
2026-08-26 18:37:36 +08:00

1471 lines
73 KiB
PHP

<?php
namespace plugin\shortplay\app\api\controller;
use app\Basic;
use app\expose\enum\State;
use plugin\control\utils\yidevs\Exception\InvalidResultException;
use plugin\control\utils\yidevs\Yidevs;
use plugin\finance\expose\helper\Account;
use plugin\finance\utils\enum\PointsBillScene;
use plugin\model\app\model\PluginModel;
use plugin\model\app\model\PluginModelTask;
use plugin\model\app\model\PluginModelTaskResult;
use plugin\model\utils\enum\ModelScene;
use plugin\model\utils\enum\ModelTaskStatus;
use plugin\model\utils\enum\ModelType;
use plugin\notification\expose\helper\Push;
use plugin\shortplay\app\model\PluginShortplayActor;
use plugin\shortplay\app\model\PluginShortplayActorCharacterLook;
use plugin\shortplay\app\model\PluginShortplayDrama;
use plugin\shortplay\app\model\PluginShortplayDramaActor;
use plugin\shortplay\app\model\PluginShortplayCharacterLook;
use plugin\shortplay\app\model\PluginShortplayDramaEpisode;
use plugin\shortplay\app\model\PluginShortplayDramaEpisodeActor;
use plugin\shortplay\app\model\PluginShortplayDramaScene;
use plugin\shortplay\app\model\PluginShortplayDramaStoryboard;
use plugin\shortplay\app\model\PluginShortplayDramaStoryboardActor;
use plugin\shortplay\app\model\PluginShortplayDramaStoryboardDialogue;
use plugin\shortplay\app\model\PluginShortplayDramaStoryboardProp;
use plugin\shortplay\app\model\PluginShortplayStyle;
use plugin\model\app\model\PluginModelVoice;
use plugin\model\utils\enum\ModelPointType;
use plugin\shortplay\app\model\PluginShortplayProp;
use plugin\shortplay\utils\enum\ActorAge;
use plugin\shortplay\utils\enum\ActorGender;
use plugin\shortplay\utils\enum\ActorSpeciesType;
use plugin\shortplay\utils\enum\ActorStatus;
use plugin\shortplay\utils\enum\PropStatus;
use plugin\shortplay\utils\enum\VoiceEmotion;
use plugin\shortplay\utils\enum\VoiceLanguage;
use plugin\shortplay\utils\PricingCalculator;
use support\Log;
use support\Request;
use support\think\Db;
use Workerman\Coroutine;
class GenerateController extends Basic
{
public function dramaCover(Request $request)
{
$id = $request->post('id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $id, 'uid' => $request->uid])->with('style')->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::DRAMA_COVER['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$whereOr = [];
$whereOr[] = ['actor.uid', '=', null];
$whereOr[] = ['actor.uid', '=', $request->uid];
$params = [];
$params['drama_id'] = $PluginShortplayDrama->id;
$PluginShortplayActor = PluginShortplayActor::actorQuery($params)->whereOr($whereOr)->order('d_actor.id', 'asc')->limit(2)->select();
$images = [];
foreach ($PluginShortplayActor as $item) {
if ($item->status == ActorStatus::GENERATED['value']) {
$images[] = $item->headimg;
}else{
$images=[];
break;
}
}
$prompts = [];
$prompts[] = '剧名:' . $PluginShortplayDrama->title;
$prompts[] = '简介:' . $PluginShortplayDrama->description;
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/draw',
'form_data' => [
'images' => $images,
'prompt' => implode(";\n", $prompts) . ";\n",
'style' => $PluginShortplayDrama->style->prompts,
'aspect_ratio' => '2:3'
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成封面', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::DrawAssistantTIGI($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $model_id;
$PluginModelTask->model_type = ModelType::DRAW['value'];
$PluginModelTask->alias_id = $PluginShortplayDrama->id;
$PluginModelTask->scene = ModelScene::DRAMA_COVER['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success('生成中');
}
public function continueEpisode(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::CREATIVE_EPISODE['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$episode_sum = (int)$request->post('episode_sum');
if (!$episode_sum) {
return $this->fail('请输入需要生成的集数');
}
$continue_episode_state = PluginModelTask::processing(['alias_id' => $PluginShortplayDrama->id, 'scene' => ModelScene::CREATIVE_EPISODE['value']]);
if ($continue_episode_state > 0) {
return $this->fail('正在生成中');
}
Db::startTrans();
try {
$PluginShortplayDramaActor = PluginShortplayDramaActor::where('drama_id', $PluginShortplayDrama->id)->with('actor')->select();
$actors = [];
foreach ($PluginShortplayDramaActor as $PluginShortplayActor) {
$actors[] = "{$PluginShortplayActor->actor->name}{{$PluginShortplayActor->actor->actor_id}}";
}
$background_description = $PluginShortplayDrama->background_description;
$outline = $PluginShortplayDrama->outline;
$pre_episode = '';
$PluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where('drama_id', $PluginShortplayDrama->id)->order('episode_no desc')->find();
if ($PluginShortplayDramaEpisode) {
// $pre_episode[] = "{$PluginShortplayDramaEpisode->episode_no}集大纲:{$PluginShortplayDramaEpisode->outline}";
$pre_episode = $PluginShortplayDramaEpisode->content;
}
$task_id = uniqid('local-');
$species = [];
$gender = [];
$age = [];
foreach (ActorSpeciesType::getOptions() as $value) {
$species[] = $value['label'] . ':' . $value['value'] . '';
}
foreach (ActorGender::getOptions() as $value) {
$gender[] = $value['label'] . ':' . $value['value'] . '';
}
foreach (ActorAge::getOptions() as $value) {
$age[] = $value['label'] . ':' . $value['value'] . '';
}
$data = [
'channels_uid' => $request->channels_uid,
'uid' => $request->uid,
'drama_id' => $PluginShortplayDrama->id,
'task_id' => $task_id,
'params' => [
'model' => $PluginModel->model_id,
'assistant' => $PluginModel->assistant_id,
'form_data' => [
'background_description' => $background_description,
'episode_duration' => $PluginShortplayDrama->episode_duration,
'outline' => $outline,
'pre_episode' => $pre_episode,
'episode_sum' => $PluginShortplayDrama->episode_sum,
'actors' => implode(',', $actors),
'episode_no' => $PluginShortplayDrama->episode_num,
'species' => implode(',', $species),
'gender' => implode(',', $gender),
'age' => implode(',', $age),
]
]
];
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::CHAT['value'];
$PluginModelTask->alias_id = $PluginShortplayDrama->id;
$PluginModelTask->scene = ModelScene::CREATIVE_EPISODE['value'];
$PluginModelTask->status = ModelTaskStatus::WAIT['value'];
$PluginModelTask->task_id = $task_id;
$PluginModelTask->execution_count = 0;
$PluginModelTask->expectation_execution_count = $episode_sum;
if ($PluginModelTask->expectation_execution_count > $PluginShortplayDrama->episode_sum - $PluginShortplayDrama->episode_num) {
$PluginModelTask->expectation_execution_count = $PluginShortplayDrama->episode_sum - $PluginShortplayDrama->episode_num;
}
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s', strtotime('+10 seconds'));
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point * $PluginModelTask->expectation_execution_count, PointsBillScene::CONSUME['value'], null, '续写分集', true);
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
Log::error('续写分集失败:' . $th->getMessage() . PHP_EOL . $th->getTraceAsString());
return $this->fail($th->getMessage());
}
return $this->success('生成中');
}
public function scene(Request $request)
{
$drama_id = $request->post('drama_id');
$episode_id = $request->post('episode_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$PluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where(['drama_id' => $PluginShortplayDrama->id, 'id' => $episode_id])->with('actors')->find();
if (!$PluginShortplayDramaEpisode) {
return $this->fail('分集不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::CREATIVE_SCENES['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$actors = [];
foreach ($PluginShortplayDramaEpisode->actors as $item) {
$actors[] = "{$item->actor->name}{{$item->actor->actor_id}}";
}
try {
$prompt = $PluginShortplayDramaEpisode->content;
$NextPluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where(['drama_id' => $PluginShortplayDrama->id, 'episode_no' => $PluginShortplayDramaEpisode->episode_no + 1])->find();
if ($NextPluginShortplayDramaEpisode) {
$next_episode_content = $NextPluginShortplayDramaEpisode->content;
} else {
$next_episode_content = '';
}
$task_id = uniqid('local-');
$data = [
'channels_uid' => $request->channels_uid,
'uid' => $request->uid,
'drama_id' => $PluginShortplayDrama->id,
'episode_id' => $PluginShortplayDramaEpisode->id,
'task_id' => $task_id,
'params' => [
'model' => $PluginModel->model_id,
'assistant' => $PluginModel->assistant_id,
'form_data' => [
'prompt' => $prompt,
'next_episode_content' => $next_episode_content,
'episode_duration' => $PluginShortplayDrama->episode_duration,
// 'episode_outline' => $outline,
'episode_num' => $PluginShortplayDrama->episode_num,
'episode_no' => $PluginShortplayDramaEpisode->episode_no,
'drama_outline' => $PluginShortplayDrama->outline,
'actors' => implode(',', $actors)
]
]
];
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $model_id;
$PluginModelTask->model_type = ModelType::CHAT['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaEpisode->id;
$PluginModelTask->scene = ModelScene::CREATIVE_SCENES['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $task_id;
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s', strtotime('+30 seconds'));
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
$consume_ids = Account::decPoints($PluginModelTask->uid, $PluginModelTask->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成场景', true);
$data['consume_ids'] = $consume_ids;
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
Coroutine::create(function () use ($data) {
try {
p('start');
$result = Yidevs::ChatAssistantCompletions($data['channels_uid'], $data['params']);
p($result);
} catch (\Throwable $th) {
Log::error('GenerateScene Error:' . $th->getMessage() . PHP_EOL . $th->getTraceAsString());
}
$taksStatus = ModelTaskStatus::FAIL['value'];
if (!empty($result)) {
Db::startTrans();
try {
$wherePublic[] = ['uid', '=', null];
$whereSelf[] = ['uid', '=', $data['uid']];
foreach ($result as $scene_key => $scene) {
$PluginShortplayDramaScene = new PluginShortplayDramaScene();
$PluginShortplayDramaScene->channels_uid = $data['channels_uid'];
$PluginShortplayDramaScene->uid = $data['uid'];
$PluginShortplayDramaScene->drama_id = $data['drama_id'];
$PluginShortplayDramaScene->episode_id = $data['episode_id'];
$PluginShortplayDramaScene->sort = $scene_key + 1;
$PluginShortplayDramaScene->title = $scene['title'];
$PluginShortplayDramaScene->scene_space = $scene['scene_space'];
$PluginShortplayDramaScene->scene_location = $scene['scene_location'];
$PluginShortplayDramaScene->scene_time = $scene['scene_time'];
$PluginShortplayDramaScene->scene_weather = $scene['scene_weather'];
$PluginShortplayDramaScene->description = $scene['description'];
if (!empty($scene['atmosphere'])) {
$PluginShortplayDramaScene->atmosphere = $scene['atmosphere'];
}
$PluginShortplayDramaScene->save();
if (empty($scene['storyboards'])) {
continue;
}
$sort = PluginShortplayDramaStoryboard::where(['drama_id' => $data['drama_id'], 'episode_id' => $data['episode_id']])->max('sort') + 1 ?? 1;
foreach ($scene['storyboards'] as $storyboard) {
$PluginShortplayDramaStoryboard = new PluginShortplayDramaStoryboard();
$PluginShortplayDramaStoryboard->channels_uid = $data['channels_uid'];
$PluginShortplayDramaStoryboard->drama_id = $data['drama_id'];
$PluginShortplayDramaStoryboard->episode_id = $data['episode_id'];
$PluginShortplayDramaStoryboard->scene_id = $PluginShortplayDramaScene->id;
$PluginShortplayDramaStoryboard->sort = $sort;
$PluginShortplayDramaStoryboard->description = $storyboard;
$PluginShortplayDramaStoryboard->save();
$sort++;
}
}
$PluginModelTask = PluginModelTask::where(['task_id' => $data['task_id'], 'model_type' => ModelType::CHAT['value']])->with(['result'])->find();
$PluginModelTask->status = ModelTaskStatus::SUCCESS['value'];
$PluginModelTask->result->result = $result;
$PluginModelTask->together(['result'])->save();
$taksStatus = ModelTaskStatus::SUCCESS['value'];
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
Log::error('GenerateScene Error:' . $th->getMessage() . PHP_EOL . $th->getTraceAsString());
}
} else {
if (!empty($data['consume_ids'])) {
Db::startTrans();
try {
Account::refund($data['uid'], $data['channels_uid'], $data['consume_ids']);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
}
if ($taksStatus == ModelTaskStatus::FAIL['value']) {
$PluginModelTask = PluginModelTask::where(['task_id' => $data['task_id'], 'model_type' => ModelType::CHAT['value']])->find();
$PluginModelTask->status = ModelTaskStatus::FAIL['value'];
$PluginModelTask->save();
}
Push::send([
'uid' => $data['uid'],
'channels_uid' => $data['channels_uid'],
'hash' => $data['drama_id'],
'event' => 'generatescenestoryboard',
], [
'drama_id' => $data['drama_id'],
'episode_id' => $data['episode_id'],
]);
});
} catch (\Throwable $th) {
return $this->exception($th);
}
return $this->success('生成中');
}
public function storyboard(Request $request)
{
$drama_id = $request->post('drama_id');
$episode_id = $request->post('episode_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$PluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where(['drama_id' => $PluginShortplayDrama->id, 'id' => $episode_id])->with('actors')->find();
if (!$PluginShortplayDramaEpisode) {
return $this->fail('分集不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::CREATIVE_STORYBOARDS['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$actors = [];
foreach ($PluginShortplayDramaEpisode->actors as $item) {
$actors[] = "{$item->actor->name}{{$item->actor->actor_id}}";
}
$props = [];
$PluginShortplayProp = PluginShortplayProp::where(['episode_id' => $PluginShortplayDramaEpisode->id])->select();
foreach ($PluginShortplayProp as $item) {
$props[] = "{$item->name}{{$item->prop_id}}";
}
$scene_list = [];
$PluginShortplayDramaScene = PluginShortplayDramaScene::where(['drama_id' => $PluginShortplayDrama->id, 'episode_id' => $PluginShortplayDramaEpisode->id])->select();
foreach ($PluginShortplayDramaScene as $item) {
$scene_list[] = "{$item->scene_space}·{$item->scene_location}·{$item->scene_time}·{$item->scene_weather}{{$item->id}}";
}
$prompt = $PluginShortplayDramaEpisode->content;
$NextPluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where(['drama_id' => $PluginShortplayDrama->id, 'episode_no' => $PluginShortplayDramaEpisode->episode_no + 1])->find();
if ($NextPluginShortplayDramaEpisode) {
$next_episode_content = $NextPluginShortplayDramaEpisode->content;
} else {
$next_episode_content = '';
}
$species_type = [];
foreach (ActorSpeciesType::getOptions() as $item) {
$species_type[] = $item['label'] . ':' . $item['value'] . '';
}
$gender = [];
foreach (ActorGender::getOptions() as $item) {
$gender[] = $item['label'] . ':' . $item['value'] . '';
}
$age = [];
foreach (ActorAge::getOptions() as $item) {
$age[] = $item['label'] . ':' . $item['value'] . '';
}
$task_id = uniqid('local-');
$data = [
'channels_uid' => $request->channels_uid,
'uid' => $request->uid,
'drama_id' => $PluginShortplayDrama->id,
'episode_id' => $PluginShortplayDramaEpisode->id,
'task_id' => $task_id,
'params' => [
'model' => $PluginModel->model_id,
'assistant' => $PluginModel->assistant_id,
'form_data' => [
'prompt' => $prompt,
'next_episode_content' => $next_episode_content,
'episode_num' => $PluginShortplayDrama->episode_num,
'episode_duration' => $PluginShortplayDrama->episode_duration,
'episode_no' => $PluginShortplayDramaEpisode->episode_no,
'sort' => 1,
'scene_list' => implode(',', $scene_list),
'actors' => implode(',', $actors),
'props' => implode(',', $props),
'species_type' => implode(',', $species_type),
'gender' => implode(',', $gender),
'age' => implode(',', $age),
]
]
];
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $model_id;
$PluginModelTask->model_type = ModelType::CHAT['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaEpisode->id;
$PluginModelTask->scene = ModelScene::CREATIVE_STORYBOARDS['value'];
$PluginModelTask->status = ModelTaskStatus::WAIT['value'];
$PluginModelTask->task_id = $task_id;
$PluginModelTask->execution_count = 0;
$PluginModelTask->expectation_execution_count = 999;
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s', strtotime('+10 seconds'));
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->exception($th);
}
return $this->success('生成中');
}
public function sceneImage(Request $request)
{
$drama_id = $request->post('drama_id');
$episode_id = $request->post('episode_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->with('style')->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$PluginShortplayDramaEpisode = PluginShortplayDramaEpisode::where(['drama_id' => $PluginShortplayDrama->id, 'id' => $episode_id])->with('actors')->find();
if (!$PluginShortplayDramaEpisode) {
return $this->fail('分集不存在');
}
$id = $request->post('id');
$PluginShortplayDramaScene = PluginShortplayDramaScene::where(['id' => $id, 'drama_id' => $PluginShortplayDrama->id, 'episode_id' => $PluginShortplayDramaEpisode->id])->find();
if (!$PluginShortplayDramaScene) {
return $this->fail('场景不存在');
}
$title = $request->post('title');
if (!empty($title)) {
$PluginShortplayDramaScene->title = $title;
}
$scene_space = $request->post('scene_space');
if (!empty($scene_space)) {
$PluginShortplayDramaScene->scene_space = $scene_space;
}
$scene_location = $request->post('scene_location');
if (!empty($scene_location)) {
$PluginShortplayDramaScene->scene_location = $scene_location;
}
$scene_time = $request->post('scene_time');
if (!empty($scene_time)) {
$PluginShortplayDramaScene->scene_time = $scene_time;
}
$scene_weather = $request->post('scene_weather');
if (!empty($scene_weather)) {
$PluginShortplayDramaScene->scene_weather = $scene_weather;
}
$description = $request->post('description');
if (!empty($description)) {
$PluginShortplayDramaScene->description = $description;
}
$atmosphere = $request->post('atmosphere');
if (!empty($atmosphere)) {
$PluginShortplayDramaScene->atmosphere = $atmosphere;
}
$PluginShortplayDramaScene->save();
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::SCENE_IMAGE['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/draw',
'form_data' => [
'id' => $PluginShortplayDramaScene->id,
'title' => $PluginShortplayDramaScene->title,
'scene_space' => $PluginShortplayDramaScene->scene_space,
'scene_location' => $PluginShortplayDramaScene->scene_location,
'scene_time' => $PluginShortplayDramaScene->scene_time,
'scene_weather' => $PluginShortplayDramaScene->scene_weather,
'description' => $PluginShortplayDramaScene->description,
'atmosphere' => $PluginShortplayDramaScene->atmosphere,
'style' => $PluginShortplayDrama->style->prompts,
'aspect_ratio' => $PluginShortplayDrama->aspect_ratio
]
];
$reference_image = $request->post('reference_image');
if (!empty($reference_image)) {
$data['form_data']['images'] = [$reference_image];
}
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成场景图片', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::DrawAssistantTIGI($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $model_id;
$PluginModelTask->model_type = ModelType::DRAW['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaScene->id;
$PluginModelTask->scene = ModelScene::SCENE_IMAGE['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
Log::error('GenerateSceneImage Error:' . $th->getMessage() . PHP_EOL . $th->getTraceAsString());
}
return $this->success();
}
public function storyboardImage(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->with('style')->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$storyboard_id = $request->post('storyboard_id');
$PluginShortplayDramaStoryboard = PluginShortplayDramaStoryboard::where(['id' => $storyboard_id, 'drama_id' => $drama_id])->find();
if (!$PluginShortplayDramaStoryboard) {
return $this->fail('分镜不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::STORYBOARD_IMAGE['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$images = [];
$PluginShortplayDramaScene = PluginShortplayDramaScene::where(['id' => $PluginShortplayDramaStoryboard->scene_id])->find();
if (!$PluginShortplayDramaScene) {
return $this->fail("分镜{$PluginShortplayDramaStoryboard->sort}:场景不存在");
}
if (!$PluginShortplayDramaScene->image) {
return $this->fail("分镜{$PluginShortplayDramaStoryboard->sort}:场景图片不存在");
}
$storyboards = $request->post('storyboards');
if ($storyboards) {
$QuotePluginShortplayDramaStoryboard = PluginShortplayDramaStoryboard::where(['drama_id' => $drama_id])->whereIn('id', $storyboards)->order('sort', 'asc')->select();
foreach ($QuotePluginShortplayDramaStoryboard as $item) {
$images[] = $item->image;
}
} else {
$images[] = $PluginShortplayDramaScene->image;
}
$whereOr = [];
$whereOr[] = ['actor.uid', '=', null];
$whereOr[] = ['actor.uid', '=', $request->uid];
$params = [];
$params['drama_id'] = $PluginShortplayDrama->id;
$params['episode_id'] = $PluginShortplayDramaStoryboard->episode_id;
$params['storyboard_id'] = $PluginShortplayDramaStoryboard->id;
$PluginShortplayActor = PluginShortplayActor::actorQuery($params)->whereOr($whereOr)->order('actor.id', 'desc')->select();
// $PluginShortplayDramaStoryboardActor = PluginShortplayDramaStoryboardActor::where(['storyboard_id' => $storyboard_id])->with('actor')->select();
foreach ($PluginShortplayActor as $item) {
if ($item->status != ActorStatus::GENERATED['value']) {
return $this->fail("分镜{$PluginShortplayDramaStoryboard->sort}:演员状态异常[" . $item->name . "]");
}
$images[] = $item->headimg;
}
$PluginShortplayDramaStoryboardProp = PluginShortplayDramaStoryboardProp::where(['storyboard_id' => $storyboard_id])->with('prop')->select();
foreach ($PluginShortplayDramaStoryboardProp as $item) {
if ($item->prop->status != PropStatus::GENERATED['value']) {
return $this->fail("分镜{$PluginShortplayDramaStoryboard->sort}:物品状态异常[" . $item->prop->name . "]");
}
if ($item->prop->image) {
$images[] = $item->prop->image;
}
}
$prompt = $request->post('prompt');
if (!$prompt) {
$prompts = [];
$prompts[] = '镜头设计:';
$prompts[] = '-景别:' . $PluginShortplayDramaStoryboard->shot_type;
$prompts[] = '-镜头视角:' . $PluginShortplayDramaStoryboard->shot_angle;
$prompts[] = "\n\n画面描述:\n" . $PluginShortplayDramaStoryboard->description;
$prompt = implode("\n", $prompts) . "\n";
}
$PluginShortplayDramaStoryboard->image_prompt = $prompt;
$PluginShortplayDramaStoryboard->save();
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/draw',
'form_data' => [
'images' => $images,
'prompt' => $prompt,
'style' => $PluginShortplayDrama->style->prompts,
'aspect_ratio' => $PluginShortplayDrama->aspect_ratio
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成分镜图片', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::DrawAssistantTIGI($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::DRAW['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaStoryboard->id;
$PluginModelTask->scene = ModelScene::STORYBOARD_IMAGE['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success('生成中');
}
public function OptimizeStoryboardPrompt(Request $request)
{
$prompt = $request->post('prompt');
if (!$prompt) {
return $this->fail('优化提示词不能为空');
}
$data = [
'model' => 2,
"messages" => [
[
"content" => "你是一位分镜大师,擅长使用AI工具",
"role" => "system"
],
]
];
$type = $request->post('type');
if ($type == ModelScene::STORYBOARD_IMAGE['value']) {
$data['messages'][] = [
"content" => "优化以下提示词用于生成高质量图片:\n" . $prompt . "\n\n只需要输出优化后的提示词,不要输出其他内容",
"role" => "user"
];
} else if ($type == ModelScene::STORYBOARD_VIDEO['value']) {
$data['messages'][] = [
"content" => "优化以下提示词用于生成高质量视频:\n" . $prompt . "\n\n只需要输出优化后的提示词,不要输出其他内容",
"role" => "user"
];
}
try {
$result = [];
Yidevs::ChatCompletions($request->channels_uid, $data, function ($ch, $data) use (&$result) {
if (empty($data['choices'][0])) {
return $data;
}
$choices = $data['choices'][0];
if (!empty($choices['message']['content'])) {
$result[] = $choices['message']['content'];
} elseif (!empty($choices['delta']['content'])) {
$result[] = $choices['delta']['content'];
}
return $data;
});
return $this->resData(['prompt' => implode('', $result)]);
} catch (\Throwable $th) {
return $this->fail($th->getMessage());
}
return $this->fail('优化失败');
}
public function characterLookCostume(Request $request)
{
$id = $request->post('id');
$PluginShortplayCharacterLook = PluginShortplayCharacterLook::where(['id' => $id, 'uid' => $request->uid])->find();
if (!$PluginShortplayCharacterLook) {
return $this->fail('装扮不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::CHARACTER_LOOK_COSTUME['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$images = [];
$costume_url = $request->post('costume_url');
$costume_reference_state = (bool)$request->post('costume_reference_state');
if ($costume_reference_state && $costume_url) {
$images[] = $costume_url;
}
$style = $request->post('style');
if ($style) {
$PluginShortplayStyle = PluginShortplayStyle::where(['id' => $style])->find();
if ($PluginShortplayStyle) {
$style = $PluginShortplayStyle->prompts;
}
} else {
if ($PluginShortplayCharacterLook->drama_id) {
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $PluginShortplayCharacterLook->drama_id])->with('style')->find();
if ($PluginShortplayDrama) {
$style = $PluginShortplayDrama->style->prompts;
}
}
}
if (!$style) {
return $this->fail('风格不存在');
}
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/draw',
'form_data' => [
'images' => $images,
'hair_style' => $PluginShortplayCharacterLook->hair_style,
'costume' => $PluginShortplayCharacterLook->costume,
'style' => $style,
'aspect_ratio' => '1:1',
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成角色换装', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::DrawAssistantTIGI($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::DRAW['value'];
$PluginModelTask->alias_id = $PluginShortplayCharacterLook->id;
$PluginModelTask->scene = ModelScene::CHARACTER_LOOK_COSTUME['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success('生成中');
}
public function characterLook(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->with('style')->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$episode_id = $request->post('episode_id');
$storyboard_id = $request->post('storyboard_id');
$actor_id = $request->post('actor_id');
$PluginShortplayActor = PluginShortplayActor::where(['id' => $actor_id])->whereOr([['uid', '=', $request->uid], ['uid', '=', null]])->find();
if (!$PluginShortplayActor) {
return $this->fail('演员不存在');
}
$character_look_id = $request->post('character_look_id');
$PluginShortplayCharacterLook = PluginShortplayCharacterLook::where(['id' => $character_look_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayCharacterLook) {
return $this->fail('装扮不存在');
}
if ($PluginShortplayCharacterLook->status !== ActorStatus::GENERATED['value']) {
return $this->fail('装扮还未完成初始化');
}
$PluginShortplayActorCharacterLook = PluginShortplayActorCharacterLook::where(['actor_id' => $actor_id, 'character_look_id' => $PluginShortplayCharacterLook->id, 'uid' => $request->uid, 'status' => ActorStatus::PENDING['value']])->find();
if ($PluginShortplayActorCharacterLook) {
return $this->fail('演员换装中');
}
$actor_costume_model_id = $request->post('actor_costume_model_id');
$PluginModel = PluginModel::where(['id' => $actor_costume_model_id, 'scene' => ModelScene::ACTOR_COSTUME['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('角色换装模型不存在');
}
$actor_costume_three_view_model_id = $request->post('actor_costume_three_view_model_id');
$ThreeViewPluginModel = PluginModel::where(['id' => $actor_costume_three_view_model_id, 'scene' => ModelScene::ACTOR_COSTUME_THREE_VIEW['value'], 'state' => State::YES['value']])->find();
if (!$ThreeViewPluginModel) {
return $this->fail('角色换装三视图模型不存在');
}
$ids = [
'channels_uid' => $request->channels_uid,
'uid' => $request->uid,
'model_id' => $PluginModel->id,
'model_model_id' => $PluginModel->model_id,
'model_points' => $PluginModel->point,
'three_view_model_points' => $ThreeViewPluginModel->point,
'assistant_id' => $PluginModel->assistant_id,
'drama_id' => $drama_id,
'episode_id' => $episode_id,
'storyboard_id' => $storyboard_id,
'actor_id' => $actor_id,
'three_view_model_id' => $ThreeViewPluginModel->id,
'three_view_model_model_id' => $ThreeViewPluginModel->model_id,
'three_view_assistant_id' => $ThreeViewPluginModel->assistant_id,
'character_look_id' => $PluginShortplayCharacterLook->id,
'host' => $request->host(),
];
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $ids['host'] . '/app/model/Notify/draw',
'form_data' => [
'prompt' => $PluginShortplayActor->remarks,
'species' => ActorSpeciesType::getText($PluginShortplayActor->species_type),
'gender' => ActorGender::getText($PluginShortplayActor->gender),
'age' => ActorAge::getText($PluginShortplayActor->age),
'overall_style' => $PluginShortplayCharacterLook->overall_style,
'status_note' => $PluginShortplayCharacterLook->status_note,
'makeup' => $PluginShortplayCharacterLook->makeup,
'hair_style' => $PluginShortplayCharacterLook->hair_style,
'costume' => $PluginShortplayCharacterLook->costume,
'style' => $PluginShortplayDrama->style->prompts,
'aspect_ratio' => '1:1',
'images' => [$PluginShortplayActor->headimg, $PluginShortplayActor->three_view_image, $PluginShortplayCharacterLook->costume_url]
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成角色换装', true);
$three_view_consume_ids = Account::decPoints($request->uid, $request->channels_uid, $ThreeViewPluginModel->point, PointsBillScene::CONSUME['value'], null, '生成角色换装三视图', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
Coroutine::create(function () use ($ids, $data, $consume_ids, $three_view_consume_ids) {
try {
$result = Yidevs::DrawAssistantTIGI($ids['channels_uid'], $data);
Db::startTrans();
try {
$PluginShortplayActorCharacterLook = new PluginShortplayActorCharacterLook();
$PluginShortplayActorCharacterLook->channels_uid = $ids['channels_uid'];
$PluginShortplayActorCharacterLook->uid = $ids['uid'];
$PluginShortplayActorCharacterLook->actor_id = $ids['actor_id'];
$PluginShortplayActorCharacterLook->status = ActorStatus::PENDING['value'];
$PluginShortplayActorCharacterLook->character_look_id = $ids['character_look_id'];
if ($ids['drama_id']) {
$PluginShortplayActorCharacterLook->drama_id = $ids['drama_id'];
}
if ($ids['episode_id']) {
$PluginShortplayActorCharacterLook->episode_id = $ids['episode_id'];
}
if ($ids['storyboard_id']) {
$PluginShortplayActorCharacterLook->storyboard_id = $ids['storyboard_id'];
}
$PluginShortplayActorCharacterLook->save();
$task = new PluginModelTask();
$task->channels_uid = $ids['channels_uid'];
$task->uid = $ids['uid'];
$task->model_id = $ids['model_id'];
$task->model_type = ModelType::DRAW['value'];
$task->alias_id = $PluginShortplayActorCharacterLook->id;
$task->scene = ModelScene::ACTOR_COSTUME['value'];
$task->status = ModelTaskStatus::PROCESSING['value'];
$task->task_id = $result['task_id'];
$task->last_heartbeat = date('Y-m-d H:i:s');
$task->consume_ids = $consume_ids;
$task->save();
$taskId = $task->id;
$taskResult = new PluginModelTaskResult();
$taskResult->task_id = $task->id;
$taskResult->channels_uid = $ids['channels_uid'];
$taskResult->params = $data;
$taskResult->save();
$data = [
'assistant' => $ids['three_view_assistant_id'],
'model' => $ids['three_view_model_model_id'],
'notify_url' => 'https://' . $ids['host'] . '/app/model/Notify/draw',
'form_data' => [
'images' => [],
'aspect_ratio' => '1:1',
'style' => $data['form_data']['style'],
]
];
$task = new PluginModelTask();
$task->channels_uid = $ids['channels_uid'];
$task->uid = $ids['uid'];
$task->model_id = $ids['three_view_model_id'];
$task->model_type = ModelType::DRAW['value'];
$task->alias_id = $PluginShortplayActorCharacterLook->id;
$task->scene = ModelScene::ACTOR_COSTUME_THREE_VIEW['value'];
$task->pre_task_id = $taskId;
$task->status = ModelTaskStatus::WAIT['value'];
$task->task_id = null;
$task->last_heartbeat = date('Y-m-d H:i:s', strtotime('+30 seconds'));
$task->consume_ids = $three_view_consume_ids;
$task->save();
$taskResult = new PluginModelTaskResult();
$taskResult->task_id = $task->id;
$taskResult->channels_uid = $ids['channels_uid'];
$taskResult->params = $data;
$taskResult->save();
Db::commit();
} catch (\Throwable $e) {
Db::rollback();
throw $e;
}
} catch (\Throwable $e) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($ids['uid'], $ids['channels_uid'], $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
if (!empty($three_view_consume_ids)) {
Db::startTrans();
try {
Account::refund($ids['uid'], $ids['channels_uid'], $three_view_consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
Log::error('GenerateActorImage Error:' . $e->getMessage());
Push::send([
'uid' => $ids['uid'],
'channels_uid' => $ids['channels_uid'],
'event' => 'generate' . strtolower(str_replace('_', '', ModelScene::ACTOR_COSTUME['value'])),
], [
'actor_id' => $ids['actor_id'],
'drama_id' => $ids['drama_id'],
'episode_id' => $ids['episode_id'],
'storyboard_id' => $ids['storyboard_id'],
]);
}
});
return $this->resData($PluginShortplayActor);
}
public function storyboardVideo(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$storyboard_id = $request->post('storyboard_id');
$PluginShortplayDramaStoryboard = PluginShortplayDramaStoryboard::where(['id' => $storyboard_id, 'drama_id' => $drama_id])->find();
if (!$PluginShortplayDramaStoryboard) {
return $this->fail('分镜不存在');
}
$model_id = $request->post('model_id');
$PluginModel = PluginModel::where(['id' => $model_id, 'scene' => ModelScene::STORYBOARD_VIDEO['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$prompt = $request->post('prompt');
if (!$prompt) {
return $this->fail('提示词不能为空');
}
$PluginShortplayDramaStoryboard->video_prompt = $prompt;
$first_image = $request->post('first_image');
if (!$first_image) {
return $this->fail('首帧图不能为空');
}
$last_image = $request->post('last_image');
$negative_prompt = $request->post('negative_prompt');
$duration = (int)$request->post('duration');
if ($duration) {
$PluginShortplayDramaStoryboard->duration = $duration;
}
$duration = max(2, min(15, floor($PluginShortplayDramaStoryboard->duration / 1000)));
$PluginShortplayDramaStoryboard->save();
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/video',
'form_data' => [
'prompt' => $prompt,
'negative_prompt' => $negative_prompt,
'first_image' => $first_image,
'last_image' => $last_image,
'duration' => $duration,
'resolution'=>'720P',
'aspect_ratio' => $PluginShortplayDrama->aspect_ratio
]
];
Db::startTrans();
try {
if ($PluginModel->point_type == ModelPointType::TIMES['value']) {
$point = $PluginModel->point;
} else {
$calculator = new PricingCalculator($PluginModel->form, $data['form_data'], $PluginModel->point);
$point = $calculator->calculate();
}
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $point, PointsBillScene::CONSUME['value'], null, '生成分镜视频', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::VideoAssistantTITV($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::TOVIDEO['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaStoryboard->id;
$PluginModelTask->scene = ModelScene::STORYBOARD_VIDEO['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->image_path = $first_image;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success('生成中');
}
public function storyboardDialogueVoice(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$storyboard_id = $request->post('storyboard_id');
$PluginShortplayDramaStoryboard = PluginShortplayDramaStoryboard::where(['id' => $storyboard_id, 'drama_id' => $drama_id])->find();
if (!$PluginShortplayDramaStoryboard) {
return $this->fail('分镜不存在');
}
$dialogue_id = $request->post('dialogue_id');
$PluginShortplayDramaStoryboardDialogue = PluginShortplayDramaStoryboardDialogue::where(['id' => $dialogue_id, 'storyboard_id' => $PluginShortplayDramaStoryboard->id])->with('actor')->find();
if (!$PluginShortplayDramaStoryboardDialogue) {
return $this->fail('台词不存在');
}
$voice = $request->post('voice');
if (empty($voice)) {
$voice = $PluginShortplayDramaStoryboardDialogue->voice;
}
if (empty($voice)) {
$ActorVoiceLevel = [
[
'model' => PluginShortplayDramaStoryboardActor::class,
'where' => [
'storyboard_id' => $PluginShortplayDramaStoryboard->id,
'actor_id' => $PluginShortplayDramaStoryboardDialogue->actor_id
]
],
[
'model' => PluginShortplayDramaEpisodeActor::class,
'where' => [
'episode_id' => $PluginShortplayDramaStoryboard->episode_id,
'actor_id' => $PluginShortplayDramaStoryboardDialogue->actor_id
]
],
[
'model' => PluginShortplayDramaActor::class,
'where' => [
'drama_id' => $PluginShortplayDrama->id,
'actor_id' => $PluginShortplayDramaStoryboardDialogue->actor_id
]
],
[
'level' => 'actor',
'model' => PluginShortplayActor::class,
'where' => [
'actor_id' => $PluginShortplayDramaStoryboardDialogue->actor_id
]
]
];
foreach ($ActorVoiceLevel as $item) {
$PluginActorVoice = $item['model']::where($item['where'])->find();
if ($PluginActorVoice && $PluginActorVoice->voice) {
$voice = $PluginActorVoice->voice;
break;
}
}
}
$prosody_volume = $request->post('prosody_volume', null);
$prosody_speed = $request->post('prosody_speed', null);
if ($prosody_volume !== null) {
$PluginShortplayDramaStoryboardDialogue->prosody_volume = $prosody_volume;
}
if ($prosody_speed !== null) {
$PluginShortplayDramaStoryboardDialogue->prosody_speed = $prosody_speed;
}
$content = $request->post('content');
if ($content) {
$PluginShortplayDramaStoryboardDialogue->content = $content;
}
$PluginShortplayDramaStoryboardDialogue->save();
$PluginModel = PluginModel::where(['id' => $voice['model_id'], 'scene' => ModelScene::DIALOGUE_VOICE['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$voice_id = $voice['voice_id'];
$voice_channel = $voice['voice_channel'];
$clone_voice_id = '';
if ($voice_channel === 'self') {
$PluginModelVoice = PluginModelVoice::where(['id' => $voice['id']])->find();
if (!$PluginModelVoice) {
return $this->fail('音色不存在');
}
$voice_id = '';
$clone_voice_id = $PluginModelVoice->voice_id;
}
if (!$clone_voice_id && !$voice_id) {
return $this->fail('未找到音色');
}
$language = empty($voice['selected_language']['value']) ? VoiceLanguage::ZH['value'] : $voice['selected_language']['value'];
$emotion = empty($voice['selected_emotion']['value']) ? VoiceEmotion::NEUTRAL['value'] : $voice['selected_emotion']['value'];
$volume = $PluginShortplayDramaStoryboardDialogue->prosody_volume;
$speed = $PluginShortplayDramaStoryboardDialogue->prosody_speed;
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/audio',
'form_data' => [
'text' => $PluginShortplayDramaStoryboardDialogue->content,
'voice_id' => $voice_id,
'clone_voice_id' => $clone_voice_id,
'emotion' => $emotion,
'volume' => $volume,
'speed' => $speed,
'language' => [$language],
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成台词语音', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::AudioAssistantTTS($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::AUDIO['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaStoryboardDialogue->id;
$PluginModelTask->scene = ModelScene::DIALOGUE_VOICE['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success();
}
public function storyboardNarrationVoice(Request $request)
{
$drama_id = $request->post('drama_id');
$PluginShortplayDrama = PluginShortplayDrama::where(['id' => $drama_id, 'uid' => $request->uid])->find();
if (!$PluginShortplayDrama) {
return $this->fail('短剧不存在');
}
$storyboard_id = $request->post('storyboard_id');
$PluginShortplayDramaStoryboard = PluginShortplayDramaStoryboard::where(['id' => $storyboard_id, 'drama_id' => $drama_id])->find();
if (!$PluginShortplayDramaStoryboard) {
return $this->fail('分镜不存在');
}
$voice = $request->post('voice');
if (!empty($voice)) {
if (!empty($voice['emotions_enum']) && empty($voice['selected_emotion'])) {
$voice['selected_emotion'] = $voice['emotions_enum'][0];
}
if (empty($voice['selected_language'])) {
$voice['selected_language'] = VoiceLanguage::ZH;
}
$PluginShortplayDrama->voice = $voice;
}
$voice = $PluginShortplayDrama->voice;
$prosody_volume = $request->post('prosody_volume', null);
$prosody_speed = $request->post('prosody_speed', null);
if ($prosody_volume !== null) {
$PluginShortplayDrama->prosody_volume = $prosody_volume;
}
if ($prosody_speed !== null) {
$PluginShortplayDrama->prosody_speed = $prosody_speed;
}
$narration = $request->post('narration');
if ($narration) {
$PluginShortplayDramaStoryboard->narration = $narration;
$PluginShortplayDramaStoryboard->save();
}
$PluginShortplayDrama->save();
$PluginModel = PluginModel::where(['id' => $voice['model_id'], 'scene' => ModelScene::STORYBOARD_NARRATION_VOICE['value'], 'state' => State::YES['value']])->find();
if (!$PluginModel) {
return $this->fail('模型不存在');
}
$voice_id = $voice['voice_id'];
$voice_channel = $voice['voice_channel'];
$clone_voice_id = '';
if ($voice_channel === 'self') {
$PluginModelVoice = PluginModelVoice::where(['id' => $voice['id']])->find();
if (!$PluginModelVoice) {
return $this->fail('音色不存在');
}
$voice_id = '';
$clone_voice_id = $PluginModelVoice->voice_id;
}
if (!$clone_voice_id && !$voice_id) {
return $this->fail('未找到音色');
}
$language = empty($voice['selected_language']['value']) ? VoiceLanguage::ZH['value'] : $voice['selected_language']['value'];
$emotion = empty($voice['selected_emotion']['value']) ? VoiceEmotion::NEUTRAL['value'] : $voice['selected_emotion']['value'];
$volume = $PluginShortplayDrama->prosody_volume;
$speed = $PluginShortplayDrama->prosody_speed;
$data = [
'assistant' => $PluginModel->assistant_id,
'model' => $PluginModel->model_id,
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/audio',
'form_data' => [
'text' => $PluginShortplayDramaStoryboard->narration,
'voice_id' => $voice_id,
'clone_voice_id' => $clone_voice_id,
'emotion' => $emotion,
'volume' => $volume,
'speed' => $speed,
'language' => [$language],
]
];
Db::startTrans();
try {
$consume_ids = Account::decPoints($request->uid, $request->channels_uid, $PluginModel->point, PointsBillScene::CONSUME['value'], null, '生成分镜旁白语音', true);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return $this->fail($th->getMessage());
}
try {
$result = Yidevs::AudioAssistantTTS($request->channels_uid, $data);
Db::startTrans();
try {
$PluginModelTask = new PluginModelTask();
$PluginModelTask->channels_uid = $request->channels_uid;
$PluginModelTask->uid = $request->uid;
$PluginModelTask->model_id = $PluginModel->id;
$PluginModelTask->model_type = ModelType::AUDIO['value'];
$PluginModelTask->alias_id = $PluginShortplayDramaStoryboard->id;
$PluginModelTask->scene = ModelScene::STORYBOARD_NARRATION_VOICE['value'];
$PluginModelTask->status = ModelTaskStatus::PROCESSING['value'];
$PluginModelTask->task_id = $result['task_id'];
$PluginModelTask->last_heartbeat = date('Y-m-d H:i:s');
$PluginModelTask->consume_ids = $consume_ids;
$PluginModelTask->save();
$PluginModelTaskResult = new PluginModelTaskResult();
$PluginModelTaskResult->task_id = $PluginModelTask->id;
$PluginModelTaskResult->channels_uid = $request->channels_uid;
$PluginModelTaskResult->params = $data;
$PluginModelTaskResult->save();
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
} catch (\Throwable $th) {
if (!empty($consume_ids)) {
Db::startTrans();
try {
Account::refund($request->uid, $request->channels_uid, $consume_ids);
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
}
}
return $this->fail($th->getMessage());
}
return $this->success();
}
}