BossBey File Manager
PHP:
8.2.30
OS:
Linux
User:
imagivibe
Root
/
home
/
imagivibe
/
public_html
/
app.imagivibe.com
/
app
/
Services
/
Youtube
📤 Upload
📝 New File
📁 New Folder
Close
Editing: YoutubeTranscriptService.php
<?php namespace App\Services\Youtube; use Exception; use Illuminate\Http\JsonResponse; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Http; class YoutubeTranscriptService { public string $searchapi = 'https://www.searchapi.io/api/v1/search'; public function getTranscript($videoUrl, $defaultLang = 'en'): JsonResponse|array { if (setting('searchapi_api_for_youtube')) { return response()->json([ 'captions' => $this->generateTranscript($videoUrl), 'status_code' => 200, ]); } try { $response = Http::timeout(30)->get($videoUrl) ->onError(function ($response) { return ['error' => 'IP blocked', 'status_code' => $response->getState()]; })->body(); $matches = []; preg_match('/"captionTracks":(\[.*?])/', $response, $matches); if (isset($matches[1])) { $captionTracks = json_decode($matches[1], true, 512, JSON_THROW_ON_ERROR); $captionTrack = collect($captionTracks)->firstWhere('languageCode', $defaultLang); if (! $captionTrack && isset($captionTracks[0]['baseUrl'])) { $captionTrack = $captionTracks[0]; } if ($captionTrack && isset($captionTrack['baseUrl'])) { $baseUrl = html_entity_decode($captionTrack['baseUrl'], ENT_QUOTES, 'UTF-8'); $response = Http::get($baseUrl); $captions = $response->body(); return response()->json([ 'captions' => $this->cleanYouTubeTranscript($captions)['text'], 'status_code' => 200, ]); } return response()->json(['error' => __('No caption tracks found.'), 'status_code' => 404]); } return response()->json(['error' => __('No captionTracks found in the response.'), 'status_code' => 404]); } catch (Exception $e) { return ['error' => $e->getMessage(), 'status_code' => 500]; } } public function cleanYouTubeTranscript(string $xmlString): array { $xml = @simplexml_load_string($xmlString, 'SimpleXMLElement', LIBXML_NOCDATA); if ($xml === false) { return [ 'array' => [], 'text' => '', ]; } $transcriptArray = []; $cleanedTranscript = ''; foreach ($xml->text as $textElement) { $start = (string) $textElement['start']; $dur = (string) $textElement['dur']; $text = trim((string) $textElement); $text = htmlspecialchars_decode($text, ENT_QUOTES); $text = preg_replace('/\s+/', ' ', $text); $transcriptArray[] = [ 'start' => $start, 'duration' => $dur, 'text' => $text, ]; $cleanedTranscript .= $text . ' '; } return [ 'array' => $transcriptArray, 'text' => trim($cleanedTranscript), ]; } public function generateTranscript(string $videoUrl): string { $videoId = $this->getYouTubeVideoId($videoUrl); if (! $videoId) { return response()->json(['error' => __('Video not found.'), 'status_code' => 404]); } if (! setting('searchapi_api_key')) { return response()->json(['error' => __('Searchapi API key is not set.'), 'status_code' => 404]); } $http = Http::get($this->searchapi, [ 'api_key' => setting('searchapi_api_key'), 'engine' => 'youtube_transcripts', 'video_id' => $videoId, ]); $transcripts = $http->json('transcripts'); if ($transcripts) { $transcriptTexts = Arr::pluck($transcripts, 'text'); if (empty($transcriptTexts)) { return response()->json(['error' => __('No transcript found.'), 'status_code' => 404]); } return implode(' ', $transcriptTexts); } return response()->json(['error' => __('Searchapi API key is not set.'), 'status_code' => 404]); } public function getYouTubeVideoId($url) { $parts = parse_url($url); if (isset($parts['query'])) { parse_str($parts['query'], $query); if (isset($query['v'])) { return $query['v']; } } if (isset($parts['path'])) { $pathParts = explode('/', trim($parts['path'], '/')); return end($pathParts); } return null; } public function getSearchapi(): string { return $this->searchapi; } }
Save
Cancel