You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
    }
}

三、关键排查要点

  1. privacyStatus参数错误:你原本将该参数设为URL,但YouTube API要求值只能是public、private或unlisted,这极有可能是上传失败的核心原因。
  2. 分块级异常捕获:给nextChunk单独加try-catch,能精准定位是哪一块上传出了问题,避免整个流程静默终止。
  3. 堆栈跟踪信息:getTraceAsString()能展示错误发生的具体代码调用链,帮你定位深层问题。
  4. 前置文件检查:提前确认文件存在、可读,避免因路径或权限问题导致的静默失败。

内容的提问来源于stack exchange,提问作者Peter Czask

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:40:25