YouTube视频上传无报错但卡在$media->nextChunk(),求排查方案
排查YouTube Data API视频上传无响应问题的异常捕获方案
你的代码执行到$media->nextChunk($chunk)时终止,说明该方法可能抛出了未被捕获的异常,或者发生了致命错误(比如内存耗尽、请求超时)。以下是增强异常捕获和调试的具体方案:
一、开启基础调试配置
先在代码最顶部添加PHP错误输出和日志配置,确保能捕捉到底层错误:
error_reporting(E_ALL); ini_set('display_errors', 1); ini_set('log_errors', 1); ini_set('error_log', '/path/to/your/php-error.log'); // 替换为你的实际日志存储路径
二、增强异常捕获的修改后代码
补充全面的异常捕获逻辑,同时在关键步骤增加前置检查:
if ($client->getAccessToken()) { try { $videoData['title'] = "test"; $videoData['description'] = "descripcio"; $videoData['tags'] = "tag1, tgag2, tag3"; // 注意:privacyStatus只能是"public"/"private"/"unlisted",你当前设置的URL是无效值,这可能是核心问题! $videoData['privacy'] = "private"; $videoPath = "/Compilations/u4vmacx0-6685l2bm5aan67nknwbp-wm.mp4"; // 前置检查:确认文件存在且可读 if (!file_exists($videoPath)) { throw new Exception("视频文件不存在:{$videoPath}"); } if (!is_readable($videoPath)) { throw new Exception("视频文件不可读,请检查权限:{$videoPath}"); } $snippet = new Google_Service_YouTube_VideoSnippet(); $snippet->setTitle($videoData['title']); $snippet->setDescription($videoData['description']); $snippet->setTags(array_map('trim', explode(",", $videoData['tags']))); // 去除标签中的空格 $snippet->setCategoryId("22"); $status = new Google_Service_YouTube_VideoStatus(); $status->privacyStatus = $videoData['privacy']; $video = new Google_Service_YouTube_Video(); $video->setSnippet($snippet); $video->setStatus($status); $chunkSizeBytes = 50 * 1024 * 1024; $client->setDefer(true); $insertRequest = $youtube->videos->insert("status,snippet", $video); $media = new Google_Http_MediaFileUpload( $client, $insertRequest, 'video/*', null, true, $chunkSizeBytes ); $media->setFileSize(filesize($videoPath)); $uploadStatus = false; // 检查文件打开是否成功 $handle = fopen($videoPath, "rb"); if (!$handle) { throw new Exception("无法打开视频文件:{$videoPath}"); } while (!$uploadStatus && !feof($handle)) { echo "读取块前<br>"; $chunk = fread($handle, $chunkSizeBytes); echo "读取块完成<br>"; // 单独捕获分块上传的异常,精准定位问题 try { $uploadStatus = $media->nextChunk($chunk); echo "当前块上传成功<br>"; } catch (Exception $e) { echo "分块上传失败:" . $e->getMessage() . "<br>"; // 输出堆栈跟踪,定位错误发生的具体位置 echo "错误堆栈:<pre>" . $e->getTraceAsString() . "</pre>"; fclose($handle); throw $e; // 抛到外层统一处理 } echo "已执行到分块上传后<br>"; } fclose($handle); $client->setDefer(false); if(!empty($uploadStatus['id'])){ $youtube_video_id = $uploadStatus['id']; echo "上传成功!视频ID:{$youtube_video_id}"; } } catch (Google_Service_Exception $e) { $statusMsg = 'YouTube服务错误:<code>'.$e->getMessage().'</code>'; $statusMsg .= '<br>错误代码:'.$e->getCode(); $statusMsg .= '<br>API响应详情:<pre>'.print_r($e->getErrors(), true).'</pre>'; } catch (Google_Exception $e) { $statusMsg = '客户端配置错误:<code>'.$e->getMessage().'</code>'; $statusMsg .= '<br>请重置会话 <a href="logout.php">Logout</a>'; $statusMsg .= '<br>错误堆栈:<pre>'.$e->getTraceAsString().'</pre>'; } catch (Exception $e) { $statusMsg = '通用执行错误:<code>'.$e->getMessage().'</code>'; $statusMsg .= '<br>错误堆栈:<pre>'.$e->getTraceAsString().'</pre>'; } catch (Error $e) { // 捕获PHP7+的致命错误 $statusMsg = '致命错误:<code>'.$e->getMessage().'</code>'; $statusMsg .= '<br>错误堆栈:<pre>'.$e->getTraceAsString().'</pre>'; } // 输出最终错误信息 if (isset($statusMsg)) { echo $statusMsg; } }
三、关键排查要点
- privacyStatus参数错误:你原本将该参数设为URL,但YouTube API要求值只能是
public、private或unlisted,这极有可能是上传失败的核心原因。 - 分块级异常捕获:给
nextChunk单独加try-catch,能精准定位是哪一块上传出了问题,避免整个流程静默终止。 - 堆栈跟踪信息:
getTraceAsString()能展示错误发生的具体代码调用链,帮你定位深层问题。 - 前置文件检查:提前确认文件存在、可读,避免因路径或权限问题导致的静默失败。
内容的提问来源于stack exchange,提问作者Peter Czask
相关产品推荐
相关产品推荐

