Explorar o código

新增音效管理和bgm管理接口

lh hai 1 día
pai
achega
6164c4c8e3

+ 28 - 0
app/Console/Test/TestCommand.php

@@ -6,6 +6,7 @@ use App\Cache\UserCache;
 use App\Facade\Site;
 use App\Libs\TikTok\Kernel\Support\Str;
 use App\Services\DeepSeek\DeepSeekService;
+use getID3;
 use GuzzleHttp\Client;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
@@ -48,6 +49,33 @@ class TestCommand extends Command
      */
     public function handle()
     {
+        exit();
+        // $audio_effects = DB::table('mp_bgms')->where('is_enabled', 1)->where('playtime_seconds', 0)->get();
+        // foreach ($audio_effects as $audio_effect) {
+        //     $id = getProp($audio_effect, 'id');
+        //     $url = getProp($audio_effect, 'bgm_url');
+        //     $index = strrpos($url, '/');
+        //     $name = 'The_Dawn';
+
+        //     // 将远程地址文件保存到本地
+        //     $filename = storage_path().'/app/public/audio_effect/' . $name;
+        //     if (!file_exists($filename)) {
+        //         $file = file_get_contents($url);
+        //         file_put_contents($filename, $file);
+        //     }
+            
+        //     $getID3 = new getID3();
+        //     $ThisFileInfo = $getID3->analyze($filename);
+        //     $seconds = floor($ThisFileInfo['playtime_seconds']) ?? 0;
+        //     if ($seconds <= 0) $seconds = 1;
+        //     DB::table('mp_bgms')->where('id', $id)->update([
+        //         'playtime_seconds'  => $seconds,
+        //         'updated_at'        => date('Y-m-d H:i:s'),
+        //     ]);
+        //     unlink($filename);
+        // }
+        // exit();
+
         // $wavPath = public_path('audio');
         // if (!file_exists($wavPath)) {
         //     return [];

+ 31 - 0
app/Http/Controllers/Book/BookController.php

@@ -145,6 +145,13 @@ class BookController extends BaseController
         return $this->success($result);
     }
 
+    // 音效管理
+    public function audioEffectList(Request $request) {
+        $data = $request->all();
+        $result = $this->bookService->audioEffectList($data);
+        return $this->success($result, [new BookTransformer(), 'newBuildAudioEffectList']);
+    }
+
     // 可选音效
     public function audioEffects(Request $request) {
         $data = $request->all();
@@ -160,6 +167,22 @@ class BookController extends BaseController
         return $this->success($result);
     }
 
+    // 编辑音效
+    public function editAudioEffect(Request $request) {
+        $data = $request->all();
+        $file = $request->file('file');
+        $result = $this->bookService->editAudioEffect($data, $file);
+        return $this->success(['success' => $result ? 1 : 0]);
+    }
+
+    
+    // bgm管理
+    public function bgmList(Request $request) {
+        $data = $request->all();
+        $result = $this->bookService->bgmList($data);
+        return $this->success($result, [new BookTransformer(), 'newBuildBgmList']);
+    }
+
     // 可选bgm
     public function bgms(Request $request) {
         $data = $request->all();
@@ -174,4 +197,12 @@ class BookController extends BaseController
         $result = $this->bookService->uploadBgm($data, $file);
         return $this->success($result);
     }
+
+    // 上传bgm
+    public function editBgm(Request $request) {
+        $data = $request->all();
+        $file = $request->file('file');
+        $result = $this->bookService->editBgm($data, $file);
+        return $this->success(['success' => $result ? 1 : 0]);
+    }
 }

+ 129 - 4
app/Services/Book/BookService.php

@@ -5,8 +5,10 @@ namespace App\Services\Book;
 use App\Consts\ErrorConst;
 use App\Facade\Site;
 use App\Libs\Utils;
+use getID3;
 use GuzzleHttp\Client;
 use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Redis;
 use OSS\Core\OssException;
 use OSS\OssClient;
@@ -273,6 +275,15 @@ class BookService
         return $result;
     }
 
+    public function audioEffectList($data) {
+        $audio_effect_name = getProp($data, 'audio_effect_name');
+        
+        $query = DB::table('mp_audio_effects')->where('is_enabled', 1);
+        if ($audio_effect_name) $query->where('audio_effect_name', 'like', '%'.$audio_effect_name.'%');
+
+        return $query->paginate();
+    }
+
     public function audioEffects($data) {
         return DB::table('mp_audio_effects')->where('is_enabled', 1)->select('audio_effect_name', 'audio_effect_url')->get()->map(function ($value) {
             return (array)$value;
@@ -283,6 +294,19 @@ class BookService
         $audio_effect_name = getProp($data, 'audio_effect_name');
 
         if (!$file) Utils::throwError('20003:请上传音频文件');
+
+        // 获取音频时长
+        $filename = $file->getPathname();
+        try {
+            $getID3 = new getID3();
+            $ThisFileInfo = $getID3->analyze($filename);
+            $seconds = floor($ThisFileInfo['playtime_seconds']) ?? 0;
+            if ($seconds <= 0) $seconds = 1;
+        } catch (\Exception $e) {
+            Log::info('音频文件解析失败: '.$e->getMessage());
+            Utils::throwError('20003:音频文件解析失败');
+        }
+
         // 验证文件格式(常见音频格式)
         if (!in_array($file->getClientOriginalExtension(), ['mp3', 'wav', 'flac', 'm4a', 'ogg', 'wma', 'cda', 'aiff', 'au', 'aac', 'amr'])) Utils::throwError('20003:音频格式错误');
         if (!$audio_effect_name) Utils::throwError('20003:请输入音频效果名称');
@@ -294,15 +318,64 @@ class BookService
 
         $boolen = DB::table('mp_audio_effects')->insert([
             'audio_effect_name' => $audio_effect_name,
-            'audio_effect_url' => $audio_effect_url,
-            'is_enabled' => 1,
-            'created_at' => date('Y-m-d H:i:s'),
-            'updated_at' => date('Y-m-d H:i:s')
+            'audio_effect_url'  => $audio_effect_url,
+            'is_enabled'        => 1,
+            'playtime_seconds'  => $seconds,
+            'created_at'        => date('Y-m-d H:i:s'),
+            'updated_at'        => date('Y-m-d H:i:s')
         ]);
         if (!$boolen) Utils::throwError('20003:添加音效失败');
         return ['audio_effect_name' => $audio_effect_name, 'audio_effect_url' => $audio_effect_url];
     }
 
+    public function editAudioEffect($data, $file) {
+        $audio_effect_id = getProp($data, 'audio_effect_id');
+        if (!$audio_effect_id) Utils::throwError('20003:请选择音效');
+        $audio_effect_name = getProp($data, 'audio_effect_name');
+        $exists_id = DB::table('mp_audio_effects')->where('audio_effect_name', $audio_effect_name)->value('id');
+        if ($exists_id && $exists_id != $audio_effect_id) Utils::throwError('20003:音效名称已存在');
+
+        $update_data = [
+            'audio_effect_name' => $audio_effect_name,
+            'updated_at' => date('Y-m-d H:i:s')
+        ];
+        if ($file) {
+            // 获取音频时长
+            $filename = $file->getPathname();
+            try {
+                $getID3 = new getID3();
+                $ThisFileInfo = $getID3->analyze($filename);
+                $seconds = floor($ThisFileInfo['playtime_seconds']) ?? 0;
+                if ($seconds <= 0) $seconds = 1;
+            } catch (\Exception $e) {
+                Log::info('音频文件解析失败: '.$e->getMessage());
+                Utils::throwError('20003:音频文件解析失败');
+            }
+            $update_data['playtime_seconds'] = $seconds;
+
+            // 验证文件格式(常见音频格式)
+            if (!in_array($file->getClientOriginalExtension(), ['mp3', 'wav', 'flac', 'm4a', 'ogg', 'wma', 'cda', 'aiff', 'au', 'aac', 'amr'])) Utils::throwError('20003:音频格式错误');
+            if (!$audio_effect_name) Utils::throwError('20003:请输入音频效果名称');
+            if (DB::table('mp_audio_effects')->where('audio_effect_name', $audio_effect_name)->exists()) Utils::throwError('20003:音效名称已存在');
+            
+            // 上传文件到oss
+            $audio_effect_url = uploadFile('audio_effects', $file, $audio_effect_name);
+            if (!$audio_effect_url) Utils::throwError('20003:上传音频文件失败');
+            $update_data['audio_effect_url'] = $audio_effect_url;
+        }
+
+        return DB::table('mp_audio_effects')->where('id', $audio_effect_id)->update($update_data);
+    }
+
+    public function bgmList($data) {
+        $bgm_name = getProp($data, 'bgm_name');
+        
+        $query = DB::table('mp_bgms')->where('is_enabled', 1);
+        if ($bgm_name) $query->where('bgm_name', 'like', '%'.$bgm_name.'%');
+
+        return $query->paginate();
+    }
+
     public function bgms($data) {
         return DB::table('mp_bgms')->where('is_enabled', 1)->select('bgm_name', 'bgm_url')->get()->map(function ($value) {
             return (array)$value;
@@ -313,6 +386,19 @@ class BookService
         $bgm_name = getProp($data, 'bgm_name');
 
         if (!$file) Utils::throwError('20003:请上传音频文件');
+
+        // 获取音频时长
+        $filename = $file->getPathname();
+        try {
+            $getID3 = new getID3();
+            $ThisFileInfo = $getID3->analyze($filename);
+            $seconds = floor($ThisFileInfo['playtime_seconds']) ?? 0;
+            if ($seconds <= 0) $seconds = 1;
+        } catch (\Exception $e) {
+            Log::info('音频文件解析失败: '.$e->getMessage());
+            Utils::throwError('20003:音频文件解析失败');
+        }
+
         // 验证文件格式(常见音频格式)
         if (!in_array($file->getClientOriginalExtension(), ['mp3', 'wav', 'flac', 'm4a', 'ogg', 'wma', 'cda', 'aiff', 'au', 'aac', 'amr'])) Utils::throwError('20003:音频格式错误');
         if (!$bgm_name) Utils::throwError('20003:请输入音频效果名称');
@@ -332,4 +418,43 @@ class BookService
         if (!$boolen) Utils::throwError('20003:添加bgm失败');
         return ['bgm_name' => $bgm_name, 'bgm_url' => $bgm_url];
     }
+
+    public function editBgm($data, $file) {
+        $bgm_id = getProp($data, 'bgm_id');
+        if (!$bgm_id) Utils::throwError('20003:请选择bgm');
+        $bgm_name = getProp($data, 'bgm_name');
+        $exists_id = DB::table('mp_bgms')->where('bgm_name', $bgm_name)->value('id');
+        if ($exists_id && $exists_id != $bgm_id) Utils::throwError('20003:bgm名称已存在');
+
+        $update_data = [
+            'bgm_name'      => $bgm_name,
+            'updated_at'    => date('Y-m-d H:i:s')
+        ];
+        if ($file) {
+            // 获取音频时长
+            $filename = $file->getPathname();
+            try {
+                $getID3 = new getID3();
+                $ThisFileInfo = $getID3->analyze($filename);
+                $seconds = floor($ThisFileInfo['playtime_seconds']) ?? 0;
+                if ($seconds <= 0) $seconds = 1;
+            } catch (\Exception $e) {
+                Log::info('音频文件解析失败: '.$e->getMessage());
+                Utils::throwError('20003:音频文件解析失败');
+            }
+            $update_data['playtime_seconds'] = $seconds;
+
+            // 验证文件格式(常见音频格式)
+            if (!in_array($file->getClientOriginalExtension(), ['mp3', 'wav', 'flac', 'm4a', 'ogg', 'wma', 'cda', 'aiff', 'au', 'aac', 'amr'])) Utils::throwError('20003:音频格式错误');
+            if (!$bgm_name) Utils::throwError('20003:请输入音频效果名称');
+            if (DB::table('mp_bgms')->where('bgm_name', $bgm_name)->exists()) Utils::throwError('20003:bgm名称已存在');
+            
+            // 上传文件到oss
+            $bgm_url = uploadFile('bgms', $file, $bgm_name);
+            if (!$bgm_url) Utils::throwError('20003:上传音频文件失败');
+            $update_data['bgm_url'] = $bgm_url;
+        }
+
+        return DB::table('mp_bgms')->where('id', $bgm_id)->update($update_data);
+    }
 }

+ 27 - 5
app/Services/Timbre/TimbreService.php

@@ -324,8 +324,8 @@ class TimbreService
             $response_arr = json_decode($response, true);
             if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
                 $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
-                Log::info('通知火山生成段落音频失败: '.$error_msg);
-                Utils::throwError('20003:通知火山生成段落音频失败');
+                Log::info('火山生成音频失败: '.$error_msg);
+                Utils::throwError('20003:火山生成音频失败');
             }
             $boolen = true;
         }
@@ -377,8 +377,8 @@ class TimbreService
             $response_arr = json_decode($response, true);
             if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
                 $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
-                Log::info('通知火山生成段落音频失败: '.$error_msg);
-                Utils::throwError('20003:通知火山生成段落音频失败');
+                Log::info('火山生成音频失败: '.$error_msg);
+                Utils::throwError('20003:火山生成音频失败');
             }
             $boolen = true;
         }
@@ -388,9 +388,31 @@ class TimbreService
 
     public function delEmotionGroup($data) {
         $group_id = getProp($data, 'group_id');
-        return DB::table('mp_emotion_groups')->where('id', $group_id)->update([
+        $url = DB::table('mp_emotion_groups')->where('id', $group_id)->value('audio_url');
+        
+        $boolen = DB::table('mp_emotion_groups')->where('id', $group_id)->update([
             'is_enabled' => 0,
             'updated_at'    => date('Y-m-d H:i:s')
         ]);
+
+        if ($boolen && $url) {
+            $boolen = false;
+            $encode_url = urlencode($url);
+            $client = new Client(['timeout' => 300, 'verify' => false]);
+            // 根据ID通过API通知合成音频
+            // $result = $client->get("http://47.240.171.155:5000/api/fileDelete?url={$encode_url}");
+            $result = $client->get("http://122.9.129.83:5000/api/fileDelete?url={$encode_url}");
+            $response = $result->getBody()->getContents();
+            $response_arr = json_decode($response, true);
+            Log::info('火山删除音频返回: '.$response);
+            if (!isset($response_arr['status']) || (int)$response_arr['status'] !== 0) {
+                $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
+                Log::info('火山删除音频失败: '.$error_msg);
+                Utils::throwError('20003:火山删除音频失败');
+            }
+            $boolen = true;
+        }
+
+        return $boolen;
     }
 }

+ 54 - 0
app/Transformer/Book/BookTransformer.php

@@ -117,4 +117,58 @@ class BookTransformer
 
         return $result;
     }
+
+    // 音效列表
+    public function newBuildAudioEffectList($data): array
+    {
+        return [
+            'meta' => getMeta($data),
+            'list'  => $this->newEachAudioEffectList($data),
+        ];
+    }
+
+    private function newEachAudioEffectList($list): array
+    {
+        $result = [];
+        if (empty($list)) return $result;
+
+        foreach ($list as $item) {
+            $result[] = [
+                'audio_effect_id'   => getProp($item, 'id'),
+                'audio_effect_name' => getProp($item, 'audio_effect_name'),
+                'audio_effect_url'  => getProp($item, 'audio_effect_url'),
+                'playtime_seconds'  => getProp($item, 'playtime_seconds'),
+                'created_at'        => transDate(getProp($item, 'created_at')),
+            ];
+        }
+
+        return $result;
+    }
+
+    // bgm列表
+    public function newBuildBgmList($data): array
+    {
+        return [
+            'meta' => getMeta($data),
+            'list'  => $this->newEachBgmList($data),
+        ];
+    }
+
+    private function newEachBgmList($list): array
+    {
+        $result = [];
+        if (empty($list)) return $result;
+
+        foreach ($list as $item) {
+            $result[] = [
+                'bgm_id'            => getProp($item, 'id'),
+                'bgm_name'          => getProp($item, 'bgm_name'),
+                'bgm_url'           => getProp($item, 'bgm_url'),
+                'playtime_seconds'  => getProp($item, 'playtime_seconds'),
+                'created_at'        => transDate(getProp($item, 'created_at')),
+            ];
+        }
+
+        return $result;
+    }
 }

+ 1 - 0
composer.json

@@ -16,6 +16,7 @@
 		"aliyuncs/oss-sdk-php": "2.6",
 		"fruitcake/laravel-cors": "^2.0",
 		"guzzlehttp/guzzle": "^7.0.1",
+		"james-heinrich/getid3": "^1.9",
 		"laravel/framework": "^8.75",
 		"laravel/sanctum": "^2.11",
 		"laravel/tinker": "^2.5",

+ 4 - 0
routes/api.php

@@ -36,11 +36,15 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
 
         // 音效
         Route::get('audioEffects', [BookController::class, 'audioEffects']);
+        Route::get('audioEffectList', [BookController::class, 'audioEffectList']);
         Route::post('uploadAudioEffect', [BookController::class, 'uploadAudioEffect']);
+        Route::post('editAudioEffect', [BookController::class, 'editAudioEffect']);
 
         // bgm
         Route::get('bgms', [BookController::class, 'bgms']);
+        Route::get('bgmList', [BookController::class, 'bgmList']);
         Route::post('uploadBgm', [BookController::class, 'uploadBgm']);
+        Route::post('editBgm', [BookController::class, 'editBgm']);
     });
 
     Route::group(['prefix' => 'timbre'], function () {