- 源码: xhadmincn/FastMovieAI (Apache 2.0) - 二开: Docker部署, Swoole改Select, route.php修复, 补update/VERSION - vendor/示例资源已gitignore
167 lines
6.6 KiB
PHP
167 lines
6.6 KiB
PHP
<?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);
|
|
}
|
|
}
|