質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.78%

Youtube apiv3 に詳しい方

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 3,312

seeeekik

score 13

UserがWeb上から動画をアップロードさせる仕組みを作りたいです。

https://developers.google.com/youtube/v3/code_samples/php?hl=ja#resumable_uploads

公式のサンプルコードだとOAuth認証しないと、アップロードできません。Userがgoogleアカウントを持っていなくてもアップロードできるように認証を挟まずにアップロードさせたいのです。

可能なのでしょうか?

GoogleDevelopperConsole->OAuth->サービスアカウント からサービスアカウント取って、試してみましたが、
An client error occurred: Failed to start the resumable upload (HTTP 401: youtube.header, Unauthorized)

と返ってきます。考えられる原因は何でしょうか?
(一応、コード載せますm(_ _)m)Cakephpでの記述です。

public function resumable_upload(){
        App::import('Vendor', 'google-api-php-client-master/src/Google/Client');
        App::import('Vendor', 'google-api-php-client-master/src/Google/Service/YouTube');
        $htmlBody ='';

        // サービスアカウント名(メールアドレス)
        $service_account_name ='service_accont_name';
        // P12キーファイルのパス
        $key_file_location = 'path/to/key';
        session_start();

        if ( !strlen($service_account_name)
               || !strlen($key_file_location)) {
            echo missingServiceAccountDetailsWarning();
        }

        $client = new Google_Client();
        $client->setScopes('https://www.googleapis.com/auth/youtube');
        //tokenをセット
        if (isset($_SESSION['service_token'])) {
            $client->setAccessToken($_SESSION['service_token']);
        }
        //Credentials(証明書)用の設定
        $key = file_get_contents($key_file_location);
        $cred = new Google_Auth_AssertionCredentials(
            $service_account_name,
            array('https://www.googleapis.com/auth/youtube.upload'),//$scope
            $key
        );
        
        $client->setAssertionCredentials($cred);
        //トークンのリフレッシュ
        if($client->getAuth()->isAccessTokenExpired()) {
            $client->getAuth()->refreshTokenWithAssertion($cred);
        }
        $_SESSION['service_token'] = $client->getAccessToken();

        //apiを操作用?インスタンスを生成
        $youtube = new Google_Service_YouTube($client);

        if (isset($_SESSION['token'])) {
          $client->setAccessToken($_SESSION['token']);
        }
);

        // Check to ensure that the access token was successfully acquired.
        if ($client->getAccessToken()) {
            echo 'getAccessToken true <br>';
          try{
                // REPLACE this value with the path to the file you are uploading.
                $videoPath = 'videopath';

                // Create a snippet with title, description, tags and category ID
                // Create an asset resource and set its snippet metadata and type.
                // This example sets the video's title, description, keyword tags, and
                // video category.
                $snippet = new Google_Service_YouTube_VideoSnippet();
                $snippet->setTitle("Test title");
                $snippet->setDescription("Test description");
                $snippet->setTags(array("tag1", "tag2"));



                // Numeric video category. See
                // https://developers.google.com/youtube/v3/docs/videoCategories/list 
                $snippet->setCategoryId("22");

                // Set the video's status to "public". Valid statuses are "public",
                // "private" and "unlisted".
                $status = new Google_Service_YouTube_VideoStatus();

                $status->privacyStatus = "public";

                // Associate the snippet and status objects with a new video resource.
                $video = new Google_Service_YouTube_Video();
                $video->setSnippet($snippet);
                $video->setStatus($status);

                // Specify the size of each chunk of data, in bytes. Set a higher value for
                // reliable connection as fewer chunks lead to faster uploads. Set a lower
                // value for better recovery on less reliable connections.
                $chunkSizeBytes = 1 * 1024 * 1024;

                // Setting the defer flag to true tells the client to return a request which can be called
                // with ->execute(); instead of making the API call immediately.
                $client->setDefer(true);

                // Create a request for the API's videos.insert method to create and upload the video.
                $insertRequest = $youtube->videos->insert("status,snippet", $video);
                // Create a MediaFileUpload object for resumable uploads.
                $media = new Google_Http_MediaFileUpload(
                    $client,
                    $insertRequest,
                    'video/*',
                    null,
                    true,
                    $chunkSizeBytes
                );
                $media->setFileSize(filesize($videoPath));


                // Read the media file and upload it chunk by chunk.
                $status = false;
                $handle = fopen($videoPath, "rb");
                debug($handle);
                while (!$status && !feof($handle)) {
                  $chunk = fread($handle, $chunkSizeBytes);
                  $status = $media->nextChunk($chunk);
                }

                fclose($handle);

                // If you want to make other calls after the file upload, set setDefer back to false
                $client->setDefer(false);

                //text 成形

                $htmlBody .= "<h3>Video Uploaded</h3><ul>";
                $htmlBody .= sprintf('<li>%s (%s)</li>',
                    $status['snippet']['title'],
                    $status['id']);
          } catch (Google_ServiceException $e) {
            $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
                htmlspecialchars($e->getMessage()));
          } catch (Google_Exception $e) {
            $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
                htmlspecialchars($e->getMessage()));
            echo $htmlBody; ・・・☆ここで401エラーが吐かれます↓
An client error occurred: Failed to start the resumable upload (HTTP 401: youtube.header, Unauthorized)
          }

          $_SESSION['token'] = $client->getAccessToken();
        } else {
          // If the user hasn't authorized the app, initiate the OAuth flow
          $state = mt_rand();
          $client->setState($state);
          $_SESSION['state'] = $state;

          $authUrl = $client->createAuthUrl();
        }

    $this->autoRender = false;
    }


  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

私もまったく同じものを開発すべく、調査中でした

その結果、公式のリファレンス
YouTube では Service Account はサポートされていないため、Service Account を使って認証しようとすると、このエラーが表示されます
との記載を見つけました

こちらのページの「YouTube API で Service Accounts が機能しない」の項にも同様の事が書いてあるのでサービスアカウントでのAPIアップロードはできないのではないかなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/02/03 16:10

    回答有難うございます。ご指摘の通りのようですね。
    DataAPIでは全て認証が必要との記述もありますが、他のAPIを試した所、確か動画リストの取得は可能でしたので、不思議に思っていました。おかげさまでスッキリしました。

    https://developers.google.com/youtube/v3/getting-started?hl=ja
    「次の表は、各種リソースでサポートされている操作を示したものです。リソースの挿入、更新、または削除を実行する操作の場合は、常にユーザー認証が必要になります。また、list メソッドについては認証されたリクエストと認証されていないリクエストの両方がサポートされています」

    「サービスアカウントでのAPIアップロードはできない」
    本当に回答ありがとうございました

    キャンセル

  • 2015/02/03 16:22

    余談ですが、代わりにVimeoという動画サービスもAPIを提供しています。

    [https://developer.vimeo.com/api/upload](https://developer.vimeo.com/api/upload)

    こちらはおそらく目的の事はできるとは思うのですが、APIでのアップロードには申請が必要で、さらに認証なしの第三者アップロードは有料プランが必要みたいなのであきらめました。

    年間利用料が払えるのであれば検討してみてはいかがでしょう。

    私も同様のサービスを作ろうと思っているので、何か良い情報がありましたらお知らせください

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る