@@ -341,4 +341,274 @@ public function downloadClip(Request $request): JsonResponse
341341 ], 500 );
342342 }
343343 }
344+
345+
346+
347+ /**
348+ * Get video info specifically for audio extraction
349+ */
350+ public function getAudioInfo (Request $ request ): JsonResponse
351+ {
352+ $ request ->validate ([
353+ 'url ' => 'required|url '
354+ ]);
355+
356+ try {
357+ $ videoInfo = $ this ->downloadService ->getVideoInfo ($ request ->input ('url ' ));
358+
359+ if ($ videoInfo ['success ' ]) {
360+ // Add audio-specific information
361+ $ audioInfo = $ videoInfo ['video_info ' ];
362+ $ audioInfo ['available_audio_formats ' ] = ['MP3 ' , 'WAV ' , 'M4A ' , 'AAC ' , 'FLAC ' , 'OGG ' ];
363+ $ audioInfo ['audio_qualities ' ] = [
364+ '96 ' => '96 kbps (Mobile) ' ,
365+ '128 ' => '128 kbps (Standard) ' ,
366+ '192 ' => '192 kbps (High) ' ,
367+ '256 ' => '256 kbps (Premium) ' ,
368+ '320 ' => '320 kbps (Maximum) '
369+ ];
370+ $ audioInfo ['estimated_audio_sizes ' ] = $ this ->calculateAudioSizes ($ audioInfo ['duration ' ] ?? '0:00 ' );
371+
372+ return response ()->json ([
373+ 'success ' => true ,
374+ 'audio_info ' => $ audioInfo
375+ ]);
376+ }
377+
378+ return response ()->json ($ videoInfo , 400 );
379+
380+ } catch (\Exception $ e ) {
381+ return response ()->json ([
382+ 'success ' => false ,
383+ 'error ' => 'Failed to get audio info: ' . $ e ->getMessage ()
384+ ], 400 );
385+ }
386+ }
387+
388+ /**
389+ * Download audio in MP3 format
390+ */
391+ public function downloadMp3 (Request $ request ): JsonResponse
392+ {
393+ $ request ->validate ([
394+ 'url ' => 'required|url ' ,
395+ 'bitrate ' => 'required|integer|in:96,128,192,256,320 ' ,
396+ 'sample_rate ' => 'sometimes|integer|in:44100,48000 ' ,
397+ 'normalize ' => 'sometimes|boolean ' ,
398+ 'remove_noise ' => 'sometimes|boolean '
399+ ]);
400+
401+ try {
402+ $ url = $ request ->input ('url ' );
403+ $ bitrate = $ request ->input ('bitrate ' , 192 );
404+ $ sampleRate = $ request ->input ('sample_rate ' , 44100 );
405+ $ normalize = $ request ->input ('normalize ' , false );
406+ $ removeNoise = $ request ->input ('remove_noise ' , false );
407+
408+ $ options = [
409+ 'sample_rate ' => $ sampleRate ,
410+ 'normalize_audio ' => $ normalize ,
411+ 'noise_reduction ' => $ removeNoise
412+ ];
413+
414+ $ result = $ this ->downloadService ->extractAudio ($ url , 'mp3 ' , $ bitrate , $ options );
415+
416+ if ($ result ['success ' ]) {
417+ // Create local download record
418+ $ download = $ this ->downloadService ->createDownload ([
419+ 'url ' => $ url ,
420+ 'quality ' => $ bitrate . 'kbps ' ,
421+ 'format ' => 'mp3 '
422+ ], $ request ->ip ());
423+
424+ return response ()->json ([
425+ 'success ' => true ,
426+ 'message ' => 'MP3 extraction started successfully ' ,
427+ 'download_id ' => $ result ['download_id ' ],
428+ 'local_id ' => $ download ->download_id ,
429+ 'format_name ' => 'MP3 Audio ' ,
430+ 'quality ' => $ bitrate . ' kbps ' ,
431+ 'info ' => $ result ['info ' ] ?? null
432+ ]);
433+ }
434+
435+ return response ()->json ($ result , 400 );
436+
437+ } catch (\Exception $ e ) {
438+ return response ()->json ([
439+ 'success ' => false ,
440+ 'error ' => 'MP3 download failed: ' . $ e ->getMessage ()
441+ ], 500 );
442+ }
443+ }
444+
445+ /**
446+ * Download audio in various formats
447+ */
448+ public function downloadAudio (Request $ request ): JsonResponse
449+ {
450+ $ request ->validate ([
451+ 'url ' => 'required|url ' ,
452+ 'format ' => 'required|string|in:mp3,wav,m4a,aac,flac,ogg ' ,
453+ 'bitrate ' => 'sometimes|integer|in:96,128,192,256,320 ' ,
454+ 'sample_rate ' => 'sometimes|integer|in:44100,48000,96000 ' ,
455+ 'bit_depth ' => 'sometimes|integer|in:16,24,32 ' ,
456+ 'normalize ' => 'sometimes|boolean ' ,
457+ 'remove_noise ' => 'sometimes|boolean '
458+ ]);
459+
460+ try {
461+ $ url = $ request ->input ('url ' );
462+ $ format = $ request ->input ('format ' );
463+ $ bitrate = $ request ->input ('bitrate ' , 192 );
464+ $ sampleRate = $ request ->input ('sample_rate ' , 44100 );
465+ $ bitDepth = $ request ->input ('bit_depth ' , 16 );
466+ $ normalize = $ request ->input ('normalize ' , false );
467+ $ removeNoise = $ request ->input ('remove_noise ' , false );
468+
469+ $ options = [
470+ 'sample_rate ' => $ sampleRate ,
471+ 'bit_depth ' => $ bitDepth ,
472+ 'normalize_audio ' => $ normalize ,
473+ 'noise_reduction ' => $ removeNoise
474+ ];
475+
476+ // Use appropriate service method based on format
477+ if ($ format === 'wav ' ) {
478+ $ result = $ this ->downloadService ->extractWAV ($ url , $ bitrate );
479+ } elseif ($ format === 'flac ' ) {
480+ $ result = $ this ->downloadService ->extractFLAC ($ url );
481+ } else {
482+ $ result = $ this ->downloadService ->extractAudio ($ url , $ format , $ bitrate , $ options );
483+ }
484+
485+ if ($ result ['success ' ]) {
486+ // Create local download record
487+ $ download = $ this ->downloadService ->createDownload ([
488+ 'url ' => $ url ,
489+ 'quality ' => $ format === 'flac ' ? 'lossless ' : $ bitrate . 'kbps ' ,
490+ 'format ' => $ format
491+ ], $ request ->ip ());
492+
493+ return response ()->json ([
494+ 'success ' => true ,
495+ 'message ' => ucfirst ($ format ) . ' extraction started successfully ' ,
496+ 'download_id ' => $ result ['download_id ' ],
497+ 'local_id ' => $ download ->download_id ,
498+ 'format_name ' => $ this ->getFormatDisplayName ($ format ),
499+ 'quality ' => $ format === 'flac ' ? 'Lossless ' : $ bitrate . ' kbps ' ,
500+ 'info ' => $ result ['info ' ] ?? null
501+ ]);
502+ }
503+
504+ return response ()->json ($ result , 400 );
505+
506+ } catch (\Exception $ e ) {
507+ return response ()->json ([
508+ 'success ' => false ,
509+ 'error ' => 'Audio download failed: ' . $ e ->getMessage ()
510+ ], 500 );
511+ }
512+ }
513+
514+ /**
515+ * Get detailed audio download progress
516+ */
517+ public function getAudioDownloadStatus (Request $ request ): JsonResponse
518+ {
519+ $ request ->validate ([
520+ 'download_id ' => 'required|string '
521+ ]);
522+
523+ try {
524+ $ downloadId = $ request ->input ('download_id ' );
525+
526+ // Get status from external API
527+ $ result = $ this ->downloadService ->getDownloadStatus ($ downloadId );
528+
529+ if ($ result ['success ' ]) {
530+ $ data = $ result ['data ' ];
531+
532+ return response ()->json ([
533+ 'success ' => true ,
534+ 'status ' => $ data ['status ' ] ?? 'processing ' ,
535+ 'progress ' => $ data ['progress ' ] ?? 0 ,
536+ 'download_url ' => $ data ['download_url ' ] ?? null ,
537+ 'file_size ' => $ data ['file_size ' ] ?? null ,
538+ 'estimated_time_remaining ' => $ data ['eta ' ] ?? null ,
539+ 'error ' => $ data ['error ' ] ?? null
540+ ]);
541+ }
542+
543+ return response ()->json ($ result , 400 );
544+
545+ } catch (\Exception $ e ) {
546+ return response ()->json ([
547+ 'success ' => false ,
548+ 'error ' => 'Failed to get download status: ' . $ e ->getMessage ()
549+ ], 400 );
550+ }
551+ }
552+
553+ /**
554+ * Calculate estimated file sizes for different audio formats
555+ */
556+ private function calculateAudioSizes (string $ duration ): array
557+ {
558+ // Parse duration (format: "mm:ss" or "h:mm:ss")
559+ $ parts = explode (': ' , $ duration );
560+ $ seconds = 0 ;
561+
562+ if (count ($ parts ) == 2 ) {
563+ $ seconds = ($ parts [0 ] * 60 ) + $ parts [1 ];
564+ } elseif (count ($ parts ) == 3 ) {
565+ $ seconds = ($ parts [0 ] * 3600 ) + ($ parts [1 ] * 60 ) + $ parts [2 ];
566+ }
567+
568+ if ($ seconds == 0 ) return [];
569+
570+ $ minutes = $ seconds / 60 ;
571+
572+ // Approximate sizes in MB per minute for different audio formats
573+ $ sizesPerMinute = [
574+ 'mp3_96 ' => 0.7 ,
575+ 'mp3_128 ' => 1.0 ,
576+ 'mp3_192 ' => 1.4 ,
577+ 'mp3_256 ' => 1.9 ,
578+ 'mp3_320 ' => 2.4 ,
579+ 'wav ' => 10.0 ,
580+ 'flac ' => 5.0 ,
581+ 'm4a ' => 0.8 ,
582+ 'aac ' => 0.9 ,
583+ 'ogg ' => 1.1
584+ ];
585+
586+ $ sizes = [];
587+ foreach ($ sizesPerMinute as $ format => $ sizePerMin ) {
588+ $ totalMB = $ minutes * $ sizePerMin ;
589+ $ sizes [$ format ] = [
590+ 'mb ' => round ($ totalMB , 1 ),
591+ 'formatted ' => $ totalMB > 1024 ? round ($ totalMB / 1024 , 2 ) . ' GB ' : round ($ totalMB , 1 ) . ' MB '
592+ ];
593+ }
594+
595+ return $ sizes ;
596+ }
597+
598+ /**
599+ * Get display name for audio format
600+ */
601+ private function getFormatDisplayName (string $ format ): string
602+ {
603+ $ displayNames = [
604+ 'mp3 ' => 'MP3 Audio ' ,
605+ 'wav ' => 'WAV Audio (Uncompressed) ' ,
606+ 'm4a ' => 'M4A Audio ' ,
607+ 'aac ' => 'AAC Audio ' ,
608+ 'flac ' => 'FLAC Audio (Lossless) ' ,
609+ 'ogg ' => 'OGG Audio '
610+ ];
611+
612+ return $ displayNames [$ format ] ?? strtoupper ($ format ) . ' Audio ' ;
613+ }
344614}
0 commit comments