think php处理 异步 url 请求 记录

1、需求 某网站 需要 AI生成音乐,生成mp3文件的时候需要等待,需要程序中实时监听mp3文件是否生成
2、用的开发框架 为php
3、文件结构
在这里插入图片描述在这里插入图片描述配置路由设置

在这里插入图片描述

Route::group('/music', function () {Route::post('/musicLyrics', 'AiMusic/musicLyrics');//Ai生成歌词流式Route::post('/selectSleepMusicList', 'AiMusic/selectSleepMusicList');//查找睡眠音乐列表Route::post('/createMusic', 'AiMusic/createMusic');//查找睡眠音乐列表Route::post('/selectMusicHistory', 'AiMusic/selectMusicHistory');//查找用户AI生成音乐历史记录Route::post('/deleteMusic', 'AiMusic/deleteMusic');//删除用户选中音乐Route::get('/musicLyricsNoStream', 'AiMusic/musicLyricsNoStream');//Ai生成歌词非流式Route::post('/publishMusic', 'AiMusic/publishMusic');//发布音乐到广场Route::get('/updateMp3FileStatus', 'AiMusic/updateMp3FileStatus');//Ai生成歌词非流式
})->middleware([app\api\middleware\AuthMiddleware::class]);

在这里插入图片描述控制器实现代码

<?php
declare (strict_types=1);namespace app\api\controller;use app\constants\Message;
use app\exception\BusinessException;
use app\service\ChatBaseService;
use app\service\ModelService;
use think\exception\ValidateException;
use think\facade\Db;class AiMusic extends Base
{//请求生成歌曲网站urlpublic $url = 'https://api.sunoaiapi.com/api/v1';//请求生成歌曲keypublic $apiKey = 'your key';public $mv = 'chirp-v3-5';public $mapList = ['limit' => '/gateway/limit','create' => '/gateway/generate/music','query' => '/gateway/query',];/*** ai 生成音乐歌词* @return*/public function musicLyrics(){$question = $this->request->all('q');if (empty($question)) {throw new BusinessException('q' . Message::NOT_NUL);}$modelId = 1;$rand = rand(00000, 99999);$conversationId = substr(md5((string)time()), 8, 16) . '-' . substr(md5((string)$rand), 8, 16) . '-' . substr(md5($question . $modelId), 8, 16);$answer = (new ChatBaseService($this->getModeName(), $conversationId))->chat((string)trim($question), (int)$this->uid, (int)$modelId);if ($answer) {return json(['code' => 200, 'msg' => $answer['message']['content']]);} else {return json(['code' => 400, 'msg' => 'AI生成歌词失败']);}}/*** ai 获取模型名字* @return*/private function getModeName(){$modelId = 1;$res = (new ModelService)->getOneById($modelId);if (empty($res)) {throw new BusinessException('model_id' . Message::NOT_NUL);}return $res['name'];}/*** ai 生成音乐歌词非流式* @return*/public function musicLyricsNoStream(){header("Access-Control-Allow-Origin: *");$command = "curl http://your ip:11434/api/chat -d '{\"model\": \"openchat:latest\",\"messages\": [{\"role\": \"user\",\"content\": \"" . $_GET['question'] . "\"}],\"stream\": false}'";$output = shell_exec($command); // 执行shell命令并将结果赋值给$output变量$data = json_decode($output, true);if ($data) {return json(['msg' => $data['message']['content']]);} else {return json(['code' => 400, 'msg' => 'AI生成歌词失败']);}}/*** 睡眠时听音乐列表* @return*/public function selectSleepMusicList(){$res = Db::name('music')->field('music_file_path,music_name,music_publicity_picture')->select();if ($res) {return json(['code' => 200, 'msg' => '获取成功', 'data' => $res]);} else {return json(['code' => 400, 'msg' => '获取失败']);}}/*** 创建歌曲* @param $this ->request 请求参数 llm 模型ID lyric 歌词 song 歌曲名称* @return  mixed JSON格式的响应数据*/public function createMusic(){$lyric = $this->request->param('lyric', '');//歌词$song = $this->request->param('song', '');//歌曲名称$tags = $this->request->param('tags', '流行');//歌曲风格$token = trim(ltrim($this->request->header('Authorization'), 'Bearer'));if (empty($song)) {throw new ValidateException('歌曲名称必填');}$url = $this->url.$this->mapList['create'];$headers = ['api-key: '.$this->apiKey,];$body = ['title' => $song,'tags' => $tags,'prompt' => $lyric,'mv' => $this->mv,];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);if (!empty($body)) {curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));}curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);curl_setopt($ch, CURLOPT_TIMEOUT, 60);curl_setopt($ch, CURLOPT_HEADER, false);curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, FALSE);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);if (!empty($headers)) {curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);}curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);$result = curl_exec($ch);curl_close($ch);if (empty($result)) {return '创建失败';}// 解码 JSON 数据$data = json_decode($result, true);if (empty($data['data'][0]['song_id'])) {return json(['code' => 400, 'msg' => '没有得到歌曲id']);} else {Db::name('ai_generated_music')->insert(['user_id' => $this->uid,'song_id' => 'https://cdn1.suno.ai/' . $data['data'][0]['song_id'] . '.mp3','title' => $data['data'][0]['title'],'music_type' => '1',//默认为我的音乐值为1'meta_tags' => $data['data'][0]['meta_tags'],'meta_prompt' => $data['data'][0]['meta_prompt'],'music_generation_state' => '生成中','music_img' => 'https://cdn1.suno.ai/image_' . $data['data'][0]['song_id'] . '.jpeg',]);$this->runAsyncGetMp3FileStatus('https://cdn1.suno.ai/' . $data['data'][0]['song_id'] . '.mp3',$token);return json(['code' => 200,'msg' => '生成歌曲成功','song_url' => 'https://cdn1.suno.ai/' . $data['data'][0]['song_id'] . '.mp3','music_img' => 'https://cdn1.suno.ai/image_' . $data['data'][0]['song_id'] . '.jpeg','music_generation_state' => '生成中',]);}}/*** 查找用户生成的音乐列表* @param 用户id* @return  当前用户的音乐列表数据*/public function selectMusicHistory(){$musicType = $this->request->param('type', '');//从页面传入的音乐类型$res = Db::name('ai_generated_music')->where([['user_id', '=', $this->uid], ['music_type', '=', $musicType]])->select();if ($res) {return json(['code' => 200, 'msg' => '获取成功', 'data' => $res]);} else {return json(['code' => 400, 'msg' => '获取失败']);}}/*** 删除用户选中音乐* @param 音乐ID* @return  删除成功或失败*/public function deleteMusic(){$musicId = $this->request->param('musicId', '');//从页面传入的音乐ID$result = Db::name('ai_generated_music')->where(['id' => (int)$musicId])->delete();if ($result) {return json(['code' => 200, 'msg' => '删除成功']);} else {return json(['code' => 400, 'msg' => '删除失败']);}}/*** 发布音乐到广场* @param 音乐ID* @return   发布音乐到广场*/public function publishMusic(){$musicId = $this->request->param('musicId', '');//从页面传入的音乐ID$res = Db::name('ai_generated_music')->where(['id' => (int)$musicId])->update(['music_type' => '0']);//更新音乐表中的音乐类型为广场音乐if ($res) {return json(['code' => 200, 'msg' => '发布音乐到广场成功']);} else {return json(['code' => 400, 'msg' => '发布音乐到广场失败或该音乐已发布']);}}/*** curl 异步调用  api/music/updateMp3FileStatus 接口 更新 mp3 音乐 文件状态* @param 音乐ID,令牌* @return*/public function runAsyncGetMp3FileStatus($songId,$token){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, "https://headsetmusic.yuzhouxiong.net/api/music/updateMp3FileStatus?songId=".$songId);  // 这个 URL 会调用异步的 PHP 脚本curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");  // 或 "POST"$authorizationToken = "Bearer ".$token;  // 替换为实际的 Tokencurl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: $authorizationToken",]);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_TIMEOUT, 1);  // 设置超时为 1 秒curl_setopt($ch, CURLOPT_NOSIGNAL, 1);  // 禁用信号curl_exec($ch);curl_close($ch);}/*** curl 异步更新mp3 文件状态 方法* @param 音乐ID* @return 数据库表h_ai_generated_music  字段 music_generation_state 为 已完成*/function updateMp3FileStatus($songId){while (true) {$headers = @get_headers($songId);// 如果获取不到响应头或者响应码不是 200,表示文件不存在if ($headers && strpos($headers[0], '200')) {$res=Db::name('ai_generated_music')->where(['song_id' => $songId])->update(['music_generation_state' => '已完成']);//更新音乐表中的音乐类型为广场音乐if ($res) {$logMessage = 'music id: '.$songId.' MP3  update success';} else {$logMessage = 'music id: '.$songId.' MP3  update failure';}// 日志文件路径$logFile = '/www/wwwroot/headset/runtime/updateMp3FileStatus.log';// 打开文件,如果文件不存在会创建,'a'模式表示追加内容$file = fopen($logFile, 'a');// 检查文件是否成功打开if ($file) {// 日志内容$logMessageTemp = "[".date('Y-m-d H:i:s')."] " . $logMessage. PHP_EOL;;// 写入日志内容fwrite($file, $logMessageTemp);// 关闭文件fclose($file);} else {echo "无法打开日志文件";}echo "处理完成";break;}// 每隔 1 秒继续检查sleep(1);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/480237.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux八股积累与笔记

1、iptables 是一个用于配置Linux内核防火墙规则的工具。四表五链&#xff1a;在iptables中&#xff0c;有四个表&#xff08;tables&#xff09;和五个链&#xff08;chains&#xff09;&#xff0c;用于管理不同类型的数据包过滤规则。如下&#xff1a; 表&#xff08;Tabl…

乐鑫发布 esp-iot-solution v2.0 版本

今天&#xff0c;乐鑫很高兴地宣布&#xff0c;esp-iot-solution v2.0 版本已经发布&#xff0c;release/v2.0 分支下的正式版本组件将为用户提供为期两年的 Bugfix 维护&#xff08;直到 2027.01.25 ESP-IDF v5.3 EOL&#xff09;。该版本将物联网开发中常用的功能进行了分类整…

【爬虫框架:feapder,管理系统 feaplat】

github&#xff1a;https://github.com/Boris-code/feapder 爬虫管理系统 feaplat&#xff1a;http://feapder.com/#/feapder_platform/feaplat 爬虫在线工具库 &#xff1a;http://www.spidertools.cn &#xff1a;https://www.kgtools.cn/1、feapder 简介 对于学习 Python…

uni-app 蓝牙开发

一. 前言 Uni-App 是一个使用 Vue.js 开发&#xff08;所有&#xff09;前端应用的框架&#xff0c;能够编译到 iOS、Android、快应用以及各种小程序等多个平台。因此&#xff0c;如果你需要快速开发一款跨平台的应用&#xff0c;比如在 H5、小程序、iOS、Android 等多个平台上…

C语言——海龟作图(对之前所有内容复习)

一.问题描述 海龟作图 设想有一只机械海龟&#xff0c;他在C程序控制下在屋里四处爬行。海龟拿了一只笔&#xff0c;这支笔或者朝上&#xff0c;或者朝下。当笔朝下时&#xff0c;海龟用笔画下自己的移动轨迹&#xff1b;当笔朝上时&#xff0c;海龟在移动过程中什么也不画。 …

【Maven】继承和聚合

5. Maven的继承和聚合 5.1 什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置&#xff0c;但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本&#xff0c;且这些模块之间不存在依赖关系&#xff0c;这就导致同一个依赖…

Android 性能优化:内存优化(理论篇)

内存作为App程序运行最重要的资源之一&#xff0c;需要运行过程中做到合理的资源分配与回收&#xff0c;不合理的内存占用轻则使得用户应用程序运行卡顿、ANR、黑屏&#xff0c;重则导致用户应用程序发生 OOM&#xff08;out of memory&#xff09;崩溃。喜马直播随着近些年的业…

技能之发布自己的依赖到npm上

目录 开始 解决 步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 运用 一直以为自己的项目在github上有了&#xff08;之传了github&#xff09;就可以进行npm install下载&#xff0c;有没有和我一样萌萌的同学。没事&#xff0c;萌萌乎乎的不犯罪。 偶然的机…

【选择排序和交换排序】直接选择排序、堆排序、冒泡排序、快速排序

【选择排序和交换排序】直接选择排序、堆排序、冒泡排序、快速排序 1. 选择排序1.1 直接选择排序1.1.1详细过程1.1.2 代码实现1.1.3 复杂度和稳定性 1.2 堆排序 2. 交换排序2.1 冒泡排序2.1.1 代码实现2.1.2 复杂度和稳定性 2.2 快速排序——挖坑法2.2.1详细过程2.2.2 代码实现…

DI依赖注入详解

DI依赖注入 声明了一个成员变量&#xff08;对象&#xff09;之后&#xff0c;在该对象上面加上注解AutoWired注解&#xff0c;那么在程序运行时&#xff0c;该对象自动在IOC容器中寻找对应的bean对象&#xff0c;并且将其赋值给成员变量&#xff0c;完成依赖注入。 AutoWire…

51c大模型~合集79

我自己的原文哦~ https://blog.51cto.com/whaosoft/12661268 #还是回谷歌好 创业一年半&#xff0c;胖了30斤&#xff0c;AI大佬感叹 回到大厂&#xff0c;和老领导重聚。 「由于工作强度和不健康的生活方式&#xff0c;我已胖了 15 公斤。」 本周一&#xff0c;知名 AI 学…

工业AI质检 AI质检智能系统 尤劲恩(上海)信息科技有限公司

来的现代化工厂&#xff0c;将逐步被无人化车间取代&#xff0c;无人工厂除了产线自动化&#xff0c;其无人质检将是绕不开的话题。尤劲恩致力于帮助工业制造领域上下游工厂减员增效、提高品质效率&#xff0c;真正实现无人质检IQC/IPQC/OQC的在线质检系统。分析生产环节真实品…

【CSS in Depth 2 精译_062】第 10 章 CSS 中的容器查询(@container)概述 + 10.1 容器查询的一个简单示例

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 ✔️ 10.1.1 容器尺寸查询的用法 ✔️ 10.2 深入理解容器10.3 与容器相关的单位10.4 容器样式查询的用法10.5 本章小结 文章目录 第 10…

ELK(Elasticsearch + logstash + kibana + Filebeat + Kafka + Zookeeper)日志分析系统

文章目录 前言架构软件包下载 一、准备工作1. Linux 网络设置2. 配置hosts文件3. 配置免密登录4. 设置 NTP 时钟同步5. 关闭防火墙6. 关闭交换分区7. 调整内存映射区域数限制8. 调整文件、进程、内存资源限制 二、JDK 安装1. 解压软件2. 配置环境变量3. 验证软件 三、安装 Elas…

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计

在现代安防视频监控领域&#xff0c;Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力&#xff0c;为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能&#xff0c;还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…

Linux 内核 调用堆栈打印函数

文章目录 内核函数调用堆栈打印1. dump_stack()一、作用二、工作原理三、实现方式四、示例实际演示 2.WARN_ON()3. panic()一、函数作用二、函数行为三、panic() 函数的参数四、使用场景 4. BUG_ON()使用场景 内核函数调用堆栈打印 1. dump_stack() dump_stack()是Linux内核中…

C语言——指针初阶(一)

目录 一.什么是指针&#xff1f;&#xff1f;&#xff1f; 指针是什么&#xff1f; 指针变量&#xff1a; 总结&#xff1a; 总结&#xff1a; 二.指针和指针类型 指针-整数&#xff1a; 总结&#xff1a; 指针的解引用 总结&#xff1a; 三.野指针 如何规避野指针 往期…

【Redis】Redis 预备知识

目录 1. 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 2. 数据结构和内部编码 3. 单线程架构 Redis 提供了5种数据结构&#xff0c;理解每种数据结构的特点对于 Redis 开发运维非常重要&#xff0c;同时掌握每种数据结构的常见命令&#xff0c;会在使用 Redis 的时…

Facebook广告无法投放是什么原因?

Facebook作为全球知名的社媒平台&#xff0c;同时也成为许多知名海外企业的广告首选。但很投手在投放过程中也发现&#xff0c;Facebook 广告投放失败或者被拒投&#xff0c;那到底为什么呢&#xff1f; 其实Facebook广告有着非常严格的审核制度&#xff0c;通常投放失败可能是…

【uniapp】轮播图

前言 Uniapp的swiper组件是一个滑块视图容器组件&#xff0c;可以在其中放置多个轮播图或滑动卡片。它是基于微信小程序的swiper组件进行封装&#xff0c;可以在不同的平台上使用&#xff0c;如微信小程序、H5、App等。 效果图 前端代码 swiper组件 <template><vi…