From 84618389e61d61bc6b8fd7c694e47cbcc6d1407b Mon Sep 17 00:00:00 2001 From: mohamadmahdi jebeli Date: Mon, 3 Nov 2025 07:58:09 +0330 Subject: [PATCH] base video creator --- lib/assets/icons/video creator.svg | 5 ++ lib/models/ai/chats_model.dart | 6 ++ lib/services/network/request_helper.dart | 1 + lib/views/ai/ai_chat_page.dart | 34 ++++++++--- lib/views/ai/ai_chat_state.dart | 59 +++++++++++-------- lib/views/ai_section/ai_section_page.dart | 19 ++++++ .../widgets/video/chat_video_player.dart | 13 +++- 7 files changed, 100 insertions(+), 37 deletions(-) create mode 100644 lib/assets/icons/video creator.svg diff --git a/lib/assets/icons/video creator.svg b/lib/assets/icons/video creator.svg new file mode 100644 index 0000000..73c6cca --- /dev/null +++ b/lib/assets/icons/video creator.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/models/ai/chats_model.dart b/lib/models/ai/chats_model.dart index 2ac87d8..4a2c942 100644 --- a/lib/models/ai/chats_model.dart +++ b/lib/models/ai/chats_model.dart @@ -117,6 +117,7 @@ class Prompts { bool? finished; bool? error; bool? audio; + bool? video; int? duration; FilesModel? fileLocal; @@ -131,6 +132,7 @@ class Prompts { this.finished, this.error, this.audio, + this.video, this.fileLocal, this.duration}); @@ -143,6 +145,7 @@ class Prompts { role = json['role']; createdAt = json['createdAt']; audio = json['audio']; + video = json['video']; duration = json['duration']; } @@ -156,6 +159,7 @@ class Prompts { data['role'] = role; data['createdAt'] = createdAt; data['audio'] = audio; + data['video'] = video; data['duration'] = duration; return data; } @@ -172,6 +176,7 @@ class Prompts { bool? finished, bool? error, bool? audio, + bool? video, int? duration, }) { return Prompts( @@ -186,6 +191,7 @@ class Prompts { finished: finished ?? this.finished, error: error ?? this.error, audio: audio ?? this.audio, + video: video ?? this.video, duration: duration ?? this.duration, ); } diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart index f9def33..2b5cdbc 100644 --- a/lib/services/network/request_helper.dart +++ b/lib/services/network/request_helper.dart @@ -236,6 +236,7 @@ class RequestHelper { static String aiSummery() => '$baseUrl/ai/aisummery'; static String aiAudio() => '$baseUrl/ai/101/aiaudio'; static String chartAnalysis() => '$baseUrl/ai/27/chart-analysis'; + static String aiVideo() => '$baseUrl/ai/102/aivideo'; static String tools() => '$baseUrl/ai/tool'; static String info() => '$baseUrl/ai/video'; static String usersAssistants({final bool personal = false}) => diff --git a/lib/views/ai/ai_chat_page.dart b/lib/views/ai/ai_chat_page.dart index 1cac369..6fcdc65 100644 --- a/lib/views/ai/ai_chat_page.dart +++ b/lib/views/ai/ai_chat_page.dart @@ -755,7 +755,9 @@ class _AiChatPageState extends State with TickerProviderStateMixin { : FilesModel(message.file.toString().replaceAll(' ', ''), duration: message.duration != null ? Duration(seconds: message.duration!) - : null)); + : null, + audio: message.audio, + video: message.video)); final isUser = message.role.toString().contains('user'); @@ -865,14 +867,28 @@ class _AiChatPageState extends State with TickerProviderStateMixin { ? Padding( padding: const EdgeInsets.fromLTRB( 16, 16, 16, 0), - child: ClipRRect( - borderRadius: - DesignConfig.lowBorderRadius, - child: ChatVideoPlayer( - src: RequestHelper.baseUrl + - file.path, - custome: const CustomControls(), - ), + child: Column( + children: [ + Container( + height: 50, + color: Colors.green, + child: Center( + child: Text( + 'VIDEO PLAYER TEST', + style: TextStyle(color: Colors.white), + ), + ), + ), + ClipRRect( + borderRadius: + DesignConfig.lowBorderRadius, + child: ChatVideoPlayer( + src: RequestHelper.baseUrl + + file.path, + custome: const CustomControls(), + ), + ), + ], ), ) : file.isImage() diff --git a/lib/views/ai/ai_chat_state.dart b/lib/views/ai/ai_chat_state.dart index 11774d7..5534f91 100644 --- a/lib/views/ai/ai_chat_state.dart +++ b/lib/views/ai/ai_chat_state.dart @@ -187,6 +187,8 @@ class AiChatState extends CoreProvier { url = '/101/aiaudio'; } else if (bot.id == 27) { url = '/27/chart-analysis'; + } else if (bot.id == 102) { + url = '/102/aivideo'; } else { url = '${isAssistants ? '/user/${bot.responseType}' : ''}/${bot.id}/${bot.name}' @@ -227,9 +229,12 @@ class AiChatState extends CoreProvier { } if (bot.id == 101) { - print('🎵 TTS Stream - Raw data: $str'); responseMessgae += str; - print('🎵 TTS Stream - Full responseMessgae: $responseMessgae'); + return; + } + + if (bot.id == 102) { + responseMessgae += str; return; } @@ -278,34 +283,41 @@ class AiChatState extends CoreProvier { int? humanMessageId; int? aiMessageId; String? audioUrl; - - if (bot.id == 101) { - print('🎵 TTS onDone - responseMessgae: $responseMessgae'); - print('🎵 TTS onDone - dataMessgae: $dataMessgae'); - } + String? videoUrl; if (bot.id == 101) { try { - print('🎵 TTS - Parsing responseMessgae directly...'); String jsonString = responseMessgae; if (jsonString.contains('}{')) { jsonString = jsonString.substring(0, jsonString.indexOf('}{') + 1); - print('🎵 TTS - Extracted first JSON: $jsonString'); } final jsonData = json.decode(jsonString); - print('🎵 TTS - Parsed JSON: $jsonData'); audioUrl = jsonData['url']?.toString(); humanMessageId = jsonData['HUMAN_MESSAGE_ID']; aiMessageId = jsonData['AI_MESSAGE_ID']; - print('🎵 TTS - audioUrl: $audioUrl'); - print( - '🎵 TTS - humanMessageId: $humanMessageId, aiMessageId: $aiMessageId'); } catch (e) { - print('🎵 TTS - ERROR parsing: $e'); + e.printError(); + return; + } + } else if (bot.id == 102) { + try { + String jsonString = responseMessgae; + + if (jsonString.contains('}{')) { + jsonString = + jsonString.substring(0, jsonString.indexOf('}{') + 1); + } + + final jsonData = json.decode(jsonString); + + videoUrl = jsonData['url']?.toString(); + humanMessageId = jsonData['HUMAN_MESSAGE_ID']; + aiMessageId = jsonData['AI_MESSAGE_ID']; + } catch (e) { e.printError(); return; } @@ -320,21 +332,18 @@ class AiChatState extends CoreProvier { } } - if (bot.id == 101) { - print('🎵 TTS - Saving message:'); - print('🎵 TTS - text: ${bot.id == 101 ? null : responseMessgae}'); - print('🎵 TTS - file: ${bot.id == 101 ? audioUrl : responseMessgae}'); - print('🎵 TTS - bot.responseType: ${bot.responseType}'); - } - messages.last.prompts.last = messages.last.prompts.last.copyWith( finished: true, - text: bot.responseType != 'text' && bot.id != 101 + text: bot.responseType != 'text' && bot.id != 101 && bot.id != 102 ? null - : (bot.id == 101 ? null : responseMessgae), - file: bot.responseType != 'text' || bot.id == 101 - ? (bot.id == 101 ? audioUrl : responseMessgae) + : (bot.id == 101 || bot.id == 102 ? null : responseMessgae), + file: bot.responseType != 'text' || bot.id == 101 || bot.id == 102 + ? (bot.id == 101 + ? audioUrl + : (bot.id == 102 ? videoUrl : responseMessgae)) : null, + audio: bot.id == 101 ? true : null, + video: bot.id == 102 ? true : null, id: aiMessageId); if (messages.last.prompts.length > 2) { messages.last.prompts[messages.last.prompts.length - 2] = messages diff --git a/lib/views/ai_section/ai_section_page.dart b/lib/views/ai_section/ai_section_page.dart index 7812821..fdac253 100644 --- a/lib/views/ai_section/ai_section_page.dart +++ b/lib/views/ai_section/ai_section_page.dart @@ -184,6 +184,25 @@ class _AiSectionPageState extends State with TickerProviderStateM aiState.startChat(AiChatArgs(bot: chartAnalysisBot)); }, ), + _AiSectionGridItem( + title: 'ساخت ویدیو', + description: 'تولید ویدیو با هوش مصنوعی', + iconPath: 'lib/assets/icons/video creator.svg', + onTap: (context) { + final aiState = context.read(); + aiState.endChat(); + + final aiVideoBot = BotsModel( + id: 102, + name: 'aivideo', + responseType: 'video', + attachmentType: [], + attachment: 0, + ); + + aiState.startChat(AiChatArgs(bot: aiVideoBot)); + }, + ), ]; } diff --git a/lib/views/widgets/video/chat_video_player.dart b/lib/views/widgets/video/chat_video_player.dart index d9a9ddf..ecab17a 100644 --- a/lib/views/widgets/video/chat_video_player.dart +++ b/lib/views/widgets/video/chat_video_player.dart @@ -31,10 +31,16 @@ class _ChatVideoPlayerState extends State { } Future _handleVideoPlayback() async { - _videoPlayerController = VideoPlayerController.network( - '${widget.src}?accessToken=${RequestService.token}'); + final videoUrl = '${widget.src}?accessToken=${RequestService.token}'; + print('🎬 ChatVideoPlayer - Initializing video...'); + print('🎬 ChatVideoPlayer - URL: $videoUrl'); + + _videoPlayerController = VideoPlayerController.network(videoUrl); await _videoPlayerController.initialize().then((_) { + print('🎬 ChatVideoPlayer - Video initialized successfully!'); + print('🎬 ChatVideoPlayer - Duration: ${_videoPlayerController.value.duration}'); + print('🎬 ChatVideoPlayer - Size: ${_videoPlayerController.value.size}'); setState(() { _chewieController = ChewieController( customControls: widget.custome, @@ -50,6 +56,7 @@ class _ChatVideoPlayerState extends State { ); }); }).catchError((e) { + print('🎬 ChatVideoPlayer - ERROR: $e'); setState(() {}); }); } @@ -58,7 +65,7 @@ class _ChatVideoPlayerState extends State { void dispose() { _videoPlayerController.pause(); _videoPlayerController.dispose(); - _chewieController?.dispose(); // Dispose of the ChewieController + _chewieController?.dispose(); super.dispose(); }