FastMovieAI AI短剧创作平台 二开基线
- 源码: xhadmincn/FastMovieAI (Apache 2.0) - 二开: Docker部署, Swoole改Select, route.php修复, 补update/VERSION - vendor/示例资源已gitignore
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\model\app\api\controller;
|
||||
|
||||
use app\Basic;
|
||||
use app\expose\enum\State;
|
||||
use plugin\model\app\model\PluginModel;
|
||||
use plugin\model\utils\enum\ModelPointType;
|
||||
use plugin\shortplay\utils\PricingCalculator;
|
||||
|
||||
class ModelController extends Basic
|
||||
{
|
||||
protected $notNeedLoginAll = ['models'];
|
||||
public function models()
|
||||
{
|
||||
$PluginModel = PluginModel::where(['state' => State::YES['value']])->order('sort asc')->field('id,channels_uid,icon,name,point,point_type,scene,description,form')->select()->each(function ($item) {
|
||||
$item->unit_point = $item->point;
|
||||
if ($item->point_type == ModelPointType::FIELD_RULE['value']) {
|
||||
$formData = [
|
||||
'resolution' => '720P',
|
||||
'duration' => 5,
|
||||
];
|
||||
$calculator = new PricingCalculator($item->form, $formData, $item->point);
|
||||
$item->point = $calculator->calculate() / 5;
|
||||
}
|
||||
});
|
||||
$models = [];
|
||||
foreach ($PluginModel as $model) {
|
||||
$models[$model->scene][] = [
|
||||
'id' => $model->id,
|
||||
'icon' => $model->icon,
|
||||
'name' => $model->name,
|
||||
'point' => $model->point,
|
||||
'scene' => $model->scene,
|
||||
'description' => $model->description,
|
||||
'form' => $model->form,
|
||||
'unit_point' => $model->unit_point,
|
||||
'unit' => ModelPointType::get($model->point_type, 'unit')
|
||||
];
|
||||
}
|
||||
return $this->resData($models);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\model\app\api\controller;
|
||||
|
||||
use app\Basic;
|
||||
use plugin\model\app\model\PluginModelTask;
|
||||
use plugin\model\utils\enum\ModelTaskStatus;
|
||||
use support\Request;
|
||||
|
||||
class TaskController extends Basic
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$limit = $request->get('limit', 10);
|
||||
$where = [];
|
||||
$where[] = ['uid', '=', $request->uid];
|
||||
$where[] = ['status', 'in', [ModelTaskStatus::WAIT['value'], ModelTaskStatus::PROCESSING['value'], ModelTaskStatus::WAIT_DOWNLOAD['value'], ModelTaskStatus::DOWNLOADING['value'], ModelTaskStatus::UPLOADING['value'], ModelTaskStatus::SUCCESS['value']]];
|
||||
$scene = $request->get('scene', 'all');
|
||||
if ($scene != 'all') {
|
||||
$where[] = ['scene', '=', $scene];
|
||||
}
|
||||
$scenes=$request->get('scenes');
|
||||
if ($scenes) {
|
||||
$where[] = ['scene', 'in', $scenes];
|
||||
}
|
||||
$model_type = $request->get('model_type', 'all');
|
||||
if ($model_type != 'all') {
|
||||
$where[] = ['model_type', '=', $model_type];
|
||||
}
|
||||
$alias_id = $request->get('alias_id');
|
||||
if ($alias_id) {
|
||||
$where[] = ['alias_id', '=', $alias_id];
|
||||
}
|
||||
$list = PluginModelTask::where($where)
|
||||
->with(['user' => function ($query) {
|
||||
$query->field('id,nickname,headimg,mobile,channels_uid');
|
||||
}, 'result' => function ($query) {
|
||||
$query->field('task_id,result,image,image_path,video_path,message,channels_uid');
|
||||
}])
|
||||
->order('id desc')
|
||||
->paginate($limit);
|
||||
return $this->resData($list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\model\app\api\controller;
|
||||
|
||||
use app\Basic;
|
||||
use app\expose\enum\State;
|
||||
use FFMpeg\FFMpeg;
|
||||
use FFMpeg\Format\Audio\Mp3;
|
||||
use FFMpeg\Format\Audio\Wav;
|
||||
use plugin\control\expose\helper\Uploads;
|
||||
use plugin\control\utils\yidevs\Yidevs;
|
||||
use plugin\model\app\model\PluginModel;
|
||||
use plugin\model\app\model\PluginModelVoice;
|
||||
use plugin\model\app\model\PluginModelVoiceText;
|
||||
use plugin\model\utils\enum\ModelScene;
|
||||
use plugin\model\utils\enum\ModelVoiceStatus;
|
||||
use plugin\notification\expose\helper\Push;
|
||||
use support\Request;
|
||||
use Webman\Http\UploadFile;
|
||||
use Workerman\Coroutine;
|
||||
|
||||
class VoiceController extends Basic
|
||||
{
|
||||
public function submit(Request $request)
|
||||
{
|
||||
$D = $request->post();
|
||||
if (empty($D['text_id'])) {
|
||||
return $this->fail('请选择文案');
|
||||
}
|
||||
if (empty($D['model_id'])) {
|
||||
return $this->fail('请选择模型');
|
||||
}
|
||||
$PluginModelVoiceText = PluginModelVoiceText::where(['id' => $D['text_id'], 'channels_uid' => $request->channels_uid])->find();
|
||||
if (!$PluginModelVoiceText) {
|
||||
return $this->fail('文案不存在');
|
||||
}
|
||||
$PluginModel = PluginModel::where(['id' => $D['model_id'], 'channels_uid' => $request->channels_uid, 'state' => State::YES['value'], 'scene' => ModelScene::DIALOGUE_VOICE['value']])->find();
|
||||
if (!$PluginModel) {
|
||||
return $this->fail('模型不存在');
|
||||
}
|
||||
$audio_url = '';
|
||||
$file = $request->file('file');
|
||||
if (empty($file)) {
|
||||
return $this->fail('请录制语音');
|
||||
}
|
||||
$fileName = uniqid('voice_') . '.wav';
|
||||
$temp_path = runtime_path('temp/' . $fileName);
|
||||
// 判断文件的mime是否为MP3或WAV
|
||||
if (!str_starts_with($file->getUploadMimeType(), 'audio/wav')) {
|
||||
// 使用phpffmpeg转换为MP3
|
||||
$ffmpeg = \FFMpeg\FFMpeg::create([
|
||||
'ffmpeg.binaries' => '/www/server/ffmpeg/ffmpeg-6.1/ffmpeg',
|
||||
'ffprobe.binaries' => '/www/server/ffmpeg/ffmpeg-6.1/ffprobe',
|
||||
]);
|
||||
$media = $ffmpeg->open($file->getRealPath());
|
||||
$wav = new Wav();
|
||||
$media->save($wav, $temp_path);
|
||||
$file = new UploadFile($temp_path, $fileName, 'audio/wav', $file->getUploadErrorCode());
|
||||
}
|
||||
if ($file->getSize() > 1024 * 1024 * 10) {
|
||||
unlink($temp_path);
|
||||
return $this->fail('语音文件大小不能超过10MB,请重新录制');
|
||||
}
|
||||
$result = Uploads::upload($request->channels_uid, $file, null, 'uploads/voice_audio');
|
||||
if (file_exists($temp_path)) {
|
||||
unlink($temp_path);
|
||||
}
|
||||
$audio_url = $result['url'];
|
||||
$PluginModelVoice = new PluginModelVoice();
|
||||
$PluginModelVoice->uid = $request->uid;
|
||||
$PluginModelVoice->channels_uid = $request->channels_uid;
|
||||
if (!empty($D['voice_id'])) {
|
||||
$PluginModelVoice = PluginModelVoice::where(['id' => $D['voice_id'], 'channels_uid' => $request->channels_uid, 'uid' => $request->uid])->find();
|
||||
if (!$PluginModelVoice) {
|
||||
return $this->fail('音色不存在');
|
||||
}
|
||||
$audio_url = $PluginModelVoice->audio_url;
|
||||
}
|
||||
$PluginModelVoice->text_id = $D['text_id'];
|
||||
$PluginModelVoice->model_id = $D['model_id'];
|
||||
if ($audio_url) {
|
||||
$PluginModelVoice->audio = $audio_url;
|
||||
}
|
||||
$PluginModelVoice->status = ModelVoiceStatus::WAIT['value'];
|
||||
$PluginModelVoice->save();
|
||||
$ids = [
|
||||
'id' => $PluginModelVoice->id,
|
||||
'uid' => $request->uid,
|
||||
'channels_uid' => $request->channels_uid,
|
||||
];
|
||||
$data = [
|
||||
'model' => $PluginModel->model_id,
|
||||
'notify_url' => 'https://' . $request->host() . '/app/model/Notify/voiceClone',
|
||||
'form_data' => [
|
||||
'audio' => $audio_url,
|
||||
]
|
||||
];
|
||||
Coroutine::create(function () use ($ids, $data) {
|
||||
$status = ModelVoiceStatus::CLONING['value'];
|
||||
try {
|
||||
$result = Yidevs::AudioVoiceClone($ids['channels_uid'], $data);
|
||||
$PluginModelVoice = PluginModelVoice::where(['id' => $ids['id'], 'channels_uid' => $ids['channels_uid']])->find();
|
||||
$PluginModelVoice->status = ModelVoiceStatus::CLONING['value'];
|
||||
$PluginModelVoice->task_id = $result['task_id'];
|
||||
$PluginModelVoice->save();
|
||||
} catch (\Throwable $th) {
|
||||
$PluginModelVoice = PluginModelVoice::where(['id' => $ids['id'], 'channels_uid' => $ids['channels_uid']])->find();
|
||||
$PluginModelVoice->status = ModelVoiceStatus::FAIL['value'];
|
||||
$PluginModelVoice->message = $th->getMessage();
|
||||
$PluginModelVoice->save();
|
||||
$status = ModelVoiceStatus::FAIL['value'];
|
||||
}
|
||||
Push::send([
|
||||
'uid' => $ids['uid'],
|
||||
'event' => 'clonevoice',
|
||||
], [
|
||||
'id' => $PluginModelVoice->id,
|
||||
'status' => $status,
|
||||
]);
|
||||
});
|
||||
return $this->resData(['voice_id' => $PluginModelVoice->id]);
|
||||
}
|
||||
public function update(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$PluginModelVoice = PluginModelVoice::where(['id' => $id, 'channels_uid' => $request->channels_uid, 'uid' => $request->uid])->find();
|
||||
if (!$PluginModelVoice) {
|
||||
return $this->fail('音色不存在');
|
||||
}
|
||||
$name = $request->post('name');
|
||||
if ($name) {
|
||||
$PluginModelVoice->name = $name;
|
||||
}
|
||||
$description = $request->post('description');
|
||||
if ($description) {
|
||||
$PluginModelVoice->description = $description;
|
||||
}
|
||||
$image = $request->post('image');
|
||||
if ($image) {
|
||||
$PluginModelVoice->image = $image;
|
||||
}
|
||||
$headimg = $request->post('headimg');
|
||||
if ($headimg) {
|
||||
$PluginModelVoice->headimg = $headimg;
|
||||
}
|
||||
$gender = $request->post('gender');
|
||||
if ($gender) {
|
||||
$PluginModelVoice->gender = $gender;
|
||||
}
|
||||
$age = $request->post('age');
|
||||
if ($age) {
|
||||
$PluginModelVoice->age = $age;
|
||||
}
|
||||
$PluginModelVoice->save();
|
||||
return $this->success('更新成功');
|
||||
}
|
||||
public function detail(Request $request)
|
||||
{
|
||||
$id = $request->get('id');
|
||||
$PluginModelVoice = PluginModelVoice::where(['id' => $id, 'channels_uid' => $request->channels_uid, 'uid' => $request->uid])->find();
|
||||
if (!$PluginModelVoice) {
|
||||
return $this->fail('音色不存在');
|
||||
}
|
||||
return $this->resData($PluginModelVoice);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\model\app\api\controller;
|
||||
|
||||
use app\Basic;
|
||||
use app\expose\enum\State;
|
||||
use plugin\model\app\model\PluginModelVoiceText;
|
||||
use support\Request;
|
||||
|
||||
class VoiceTextController extends Basic
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$where = [];
|
||||
$where[] = ['channels_uid', '=', $request->channels_uid];
|
||||
$where[] = ['state', '=', State::YES['value']];
|
||||
$text = $request->get('text');
|
||||
if ($text) {
|
||||
$where[] = ['text', 'like', "%{$text}%"];
|
||||
}
|
||||
$list = PluginModelVoiceText::where($where)->order('id desc')->select();
|
||||
return $this->resData($list);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user