Initial commit: 교육 프로젝트 배포
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/**
|
||||
* YouTube Data API v3 프록시 + Gemini AI 무료 요약 (최종 완성본)
|
||||
*/
|
||||
require __DIR__ . '/../../bbs/auth.php';
|
||||
edu_require_login();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// ★ 서비스 키 설정
|
||||
define('YOUTUBE_API_KEY', 'AIzaSyDfj_8oN6cbkmxn2zS77_CG-OB6xF8ywpI');
|
||||
define('GEMINI_API_KEY', 'AIzaSyAlQXuhXroeoWmh0u_N3Qq9tgUMLYuucWI');
|
||||
|
||||
$video_id = isset($_GET['video_id']) ? trim($_GET['video_id']) : '';
|
||||
$video_id = extract_yt_id($video_id);
|
||||
|
||||
if (!$video_id) {
|
||||
echo json_encode(['success' => false, 'message' => '유효하지 않은 ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* YouTube ID 추출 함수
|
||||
*/
|
||||
function extract_yt_id($input)
|
||||
{
|
||||
if (preg_match('/^[a-zA-Z0-9_-]{11}$/', $input))
|
||||
return $input;
|
||||
if (preg_match('#youtu\.be/([a-zA-Z0-9_-]{11})#', $input, $m))
|
||||
return $m[1];
|
||||
if (preg_match('#[?&]v=([a-zA-Z0-9_-]{11})#', $input, $m))
|
||||
return $m[1];
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gemini AI 요약 함수 (보안 및 통신 강화)
|
||||
*/
|
||||
function get_gemini_summary($text)
|
||||
{
|
||||
if (empty(GEMINI_API_KEY) || GEMINI_API_KEY === 'YOUR_GEMINI_API_KEY_HERE')
|
||||
return null;
|
||||
|
||||
// $url = 'https://generativelanguage.googleapis.com/v1/models/gemini-1.5-flash:generateContent?key=' . GEMINI_API_KEY;
|
||||
$url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=' . GEMINI_API_KEY;
|
||||
$data = [
|
||||
'contents' => [
|
||||
[
|
||||
'parts' => [['text' => "너는 교육 콘텐츠 에디터야. 아래 유튜브 설명에서 타임라인(00:00)과 구독/좋아요 요청은 완전히 제외하고, 핵심 내용만 직장인을 위해 3문장 이내로 요약해줘:\n\n" . mb_substr($text, 0, 3000, 'UTF-8')]]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36');
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code === 200 && $response) {
|
||||
$res = json_decode($response, true);
|
||||
$result = $res['candidates'][0]['content']['parts'][0]['text'] ?? null;
|
||||
return $result ? trim($result) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. YouTube API 호출 (데이터 가져오기 로직 복구)
|
||||
$api_url = "https://www.googleapis.com/youtube/v3/videos?id={$video_id}&part=snippet,contentDetails&key=" . YOUTUBE_API_KEY;
|
||||
$yt_res = @file_get_contents($api_url);
|
||||
$yt_data = json_decode($yt_res, true);
|
||||
|
||||
if (empty($yt_data['items'])) {
|
||||
echo json_encode(['success' => false, 'message' => '영상을 찾을 수 없습니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$item = $yt_data['items'][0];
|
||||
$yt_title = $item['snippet']['title'] ?? '';
|
||||
$yt_desc_raw = $item['snippet']['description'] ?? '';
|
||||
$duration = $item['contentDetails']['duration'] ?? 'PT0S';
|
||||
|
||||
// 2. 요약 처리 (AI 시도)
|
||||
$summary = get_gemini_summary($yt_desc_raw);
|
||||
|
||||
// [핵심] AI가 실패하거나, 결과에 여전히 타임라인(00:00)이 포함된 경우 강력한 수동 필터 작동
|
||||
if (!$summary || preg_match('/[0-9]{1,2}:[0-9]{2}/', $summary)) {
|
||||
$text = $yt_desc_raw;
|
||||
|
||||
// (1) 타임라인 제거 (줄 시작이 숫자:숫자인 모든 줄 삭제)
|
||||
$text = preg_replace('/^[ ]*[0-9]{1,2}:[0-9]{2}.*$/m', '', $text);
|
||||
|
||||
// (2) 구독/좋아요/광고 문구가 포함된 문장 삭제
|
||||
$patterns = ['구독', '좋아요', '알림설정', '인스타그램', '페이스북', '문의'];
|
||||
foreach ($patterns as $p) {
|
||||
$text = preg_replace('/[^.!?\n]*?' . $p . '[^.!?\n]*?[.!?\n]?/u', '', $text);
|
||||
}
|
||||
|
||||
// (3) 해시태그 및 이모지 제거
|
||||
$text = preg_replace('/#[^\s#]+/u', '', $text);
|
||||
$text = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $text);
|
||||
|
||||
// (4) 공백 정리 및 200자 절삭
|
||||
$text = preg_replace('/\s+/', ' ', trim($text));
|
||||
$summary = mb_substr($text, 0, 200, 'UTF-8');
|
||||
if (mb_strlen($text, 'UTF-8') > 200)
|
||||
$summary .= '...';
|
||||
}
|
||||
|
||||
// 3. 재생 시간 계산 (ISO 8601 -> 초)
|
||||
preg_match('/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/', $duration, $m);
|
||||
$content_tm = ((int) ($m[1] ?? 0) * 3600) + ((int) ($m[2] ?? 0) * 60) + (int) ($m[3] ?? 0);
|
||||
|
||||
// 최종 결과 출력
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'yt_title' => $yt_title,
|
||||
'description' => $summary,
|
||||
'content_tm' => $content_tm,
|
||||
'duration_fmt' => sprintf('%d:%02d', intdiv($content_tm, 60), $content_tm % 60),
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
Reference in New Issue
Block a user