Youtube data api Youtube实时流媒体API提供livePermissionBlocked错误

Youtube data api Youtube实时流媒体API提供livePermissionBlocked错误,youtube-data-api,google-authentication,service-accounts,youtube-livestreaming-api,Youtube Data Api,Google Authentication,Service Accounts,Youtube Livestreaming Api,我正在尝试使用服务帐户委派设置youtube实时流媒体API。我已经在我的域上完成了服务帐户委派的所有必要步骤。 我有一个youtube频道,由一个电子邮件id为该域名的用户拥有。该频道拥有超过1万名订户,拥有直播的所有必要权限(我可以通过youtube studio直播)。 在使用youtube java API时,我遇到以下错误: { "code" : 403, "errors" : [ { "domain" : &

我正在尝试使用服务帐户委派设置youtube实时流媒体API。我已经在我的域上完成了服务帐户委派的所有必要步骤。 我有一个youtube频道,由一个电子邮件id为该域名的用户拥有。该频道拥有超过1万名订户,拥有直播的所有必要权限(我可以通过youtube studio直播)。 在使用youtube java API时,我遇到以下错误:

{
  "code" : 403,
  "errors" : [ {
    "domain" : "youtube.liveBroadcast",
    "message" : "The user is blocked from live streaming.",
    "reason" : "livePermissionBlocked",
    "extendedHelp" : "https://support.google.com/youtube/answer/2853834"
  } ],
  "message" : "The user is blocked from live streaming."
}
我附上我的代码以供参考

    private static final Collection<String> SCOPES =
            Arrays.asList("https://www.googleapis.com/auth/youtube.force-ssl");
    private static final String APPLICATION_NAME = "youtubeLive";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /**
     * Create an authorized Credential object.
     *
     * @return an authorized Credential object.
     * @throws IOException
     */
    public static Credential authorize(final NetHttpTransport httpTransport) throws IOException, GeneralSecurityException {
        // Load client secrets.
        InputStream in = new FileInputStream(CLIENT_SECRETS);
//        GoogleClientSecrets clientSecrets =
//                GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
//        // Build flow and trigger user authorization request.
//        GoogleAuthorizationCodeFlow flow =
//                new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
//                        .build();
//        Credential credential = new AuthorizationCodeInstalledApp(flow, null).authorize("user");
//        GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(CLIENT_SECRETS))
//                .createScoped(SCOPES);
        GoogleCredential credential = new GoogleCredential.Builder()
                .setServiceAccountScopes(SCOPES)
                .setServiceAccountPrivateKeyFromP12File(new File("/Users/ashishjindal/Downloads/youtubelive-291213-be89f6b31144.p12"))
                .setServiceAccountId("a******@youtubelive****.iam.gserviceaccount.com")
                .setServiceAccountUser("USER@MY_DOMAIN.COM")
                .setJsonFactory(JSON_FACTORY)
                .setTransport(httpTransport)
                .build();
        return credential;
    }

    /**
     * Build and return an authorized API client service.
     *
     * @return an authorized API client service
     * @throws GeneralSecurityException, IOException
     */
    public static YouTube getService() throws GeneralSecurityException, IOException {
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        Credential credential = authorize(httpTransport);
        return new YouTube.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();
    }



    @Scheduled(fixedDelay = 1000l)
    public void test() throws IOException, GeneralSecurityException {
        YouTube youtubeService = getService();
        LiveBroadcast liveBroadcast = new LiveBroadcast();

        // Add the contentDetails object property to the LiveBroadcast object.
        LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();

        contentDetails.setEnableClosedCaptions(true);
        contentDetails.setEnableContentEncryption(true);
        contentDetails.setEnableDvr(true);
        contentDetails.setEnableEmbed(true);
        contentDetails.setEnableAutoStart(true);
        contentDetails.setRecordFromStart(true);
        contentDetails.setStartWithSlate(true);
        liveBroadcast.setContentDetails(contentDetails);

        LiveBroadcastSnippet snippet = new LiveBroadcastSnippet();
        snippet.setScheduledEndTime(new DateTime("2030-10-10T00:00:00"));
        snippet.setScheduledStartTime(new DateTime("2029-10-10T00:00:00"));
        snippet.setTitle("Test broadcast");
        snippet.setChannelId("CHANNEL ID OWNED BY MY USER");
        liveBroadcast.setSnippet(snippet);

        LiveBroadcastStatus status = new LiveBroadcastStatus();
        status.setPrivacyStatus("unlisted");
        liveBroadcast.setStatus(status);

        YouTube.LiveBroadcasts.Insert request = youtubeService.liveBroadcasts()
                .insert("snippet,contentDetails,status", liveBroadcast);
        liveBroadcast = request.execute();
        System.out.println(response);
     }
私有静态最终收集范围=
Arrays.asList(“https://www.googleapis.com/auth/youtube.force-ssl");
私有静态最终字符串应用程序\u NAME=“youtubeLive”;
私有静态最终JsonFactory JSON_FACTORY=JacksonFactory.getDefaultInstance();
/**
*创建授权凭据对象。
*
*@返回授权凭证对象。
*@抛出异常
*/
公共静态凭据授权(最终NetHttpTransport httpTransport)引发IOException、GeneralSecurityException{
//加载客户端机密。
InputStream in=新文件InputStream(客户端机密);
//谷歌客户机密=
//load(JSON_工厂,新的InputStreamReader(in));
////生成流并触发用户授权请求。
//GoogleAuthorizationCodeFlow=
//新的GoogleAuthorizationCodeFlow.Builder(httpTransport、JSON_工厂、clientSecrets、SCOPES)
//.build();
//凭证凭证=新授权代码InstalledApp(流,空)。授权(“用户”);
//GoogleCredential credential=GoogleCredential.fromStream(新文件输入流(客户端密码))
//.createScoped(范围);
GoogleCredential credential=新建GoogleCredential.Builder()
.setServiceAccountScopes(范围)
.SetServiceAccountPrivateKeyFromp12文件(新文件(“/Users/ashishjindal/Downloads/youtubelive-291213-be89F6B3114.p12”))
.setServiceAccount(“a*********@youtubelive****.iam.gserviceaccount.com”)
.setServiceAccountUser(“USER@MY_DOMAIN.COM")
.setJsonFactory(JSON_工厂)
.setTransport(httpTransport)
.build();
返回凭证;
}
/**
*生成并返回授权的API客户端服务。
*
*@返回授权的API客户端服务
*@抛出GeneralSecurityException,IOException
*/
公共静态YouTube getService()引发GeneralSecurityException,IOException{
最终NetHttpTransport-httpTransport=GoogleNetHttpTransport.newTrustedTransport();
凭证=授权(httpTransport);
返回新的YouTube.Builder(httpTransport、JSON_工厂、凭证)
.setApplicationName(应用程序名称)
.build();
}
@计划(固定延迟=1000l)
public void test()引发IOException、GeneralSecurityException{
YouTube YouTube服务=getService();
LiveBroadcast LiveBroadcast=新的LiveBroadcast();
//将contentDetails对象属性添加到LiveBroadcast对象。
LiveBroadcastContentDetails contentDetails=新的LiveBroadcastContentDetails();
contentDetails.setEnableClosedCaptions(true);
contentDetails.setEnableContentEncryption(true);
contentDetails.setEnableDvr(true);
contentDetails.setEnableEmbed(true);
contentDetails.setEnableAutoStart(true);
contentDetails.setRecordFromStart(true);
contentDetails.setStartWithState(true);
liveBroadcast.setContentDetails(contentDetails);
LiveBroadcastSnippet snippet=新的LiveBroadcastSnippet();
snippet.setScheduledEndTime(新日期时间(“2030-10-10T00:00:00”);
setScheduledStartTime(新日期时间(“2029-10-10T00:00:00”);
setTitle(“测试广播”);
setChannelId(“我的用户拥有的通道ID”);
liveBroadcast.setSnippet(片段);
LiveBroadcastStatus=新的LiveBroadcastStatus();
状态。setPrivacyStatus(“未上市”);
实时广播。设置状态(状态);
YouTube.LiveBroadcasts.Insert request=youtubeService.LiveBroadcasts()
.插入(“片段、内容详细信息、状态”,直播);
liveBroadcast=request.execute();
System.out.println(响应);
}
编辑:我已经确定了根本原因。我正在传递属于该用户进一步拥有的品牌帐户的频道Id。用户可以在youtube上拥有多个品牌帐户。现在我的新问题是如何使用服务帐户模拟品牌帐户。 我发现了一些有用的线索:


YouTube API不支持服务帐户(与其他Google API一样)

以下是引用API官方文件的部分(以下重点是我的):

服务帐户不适用于YouTube数据API调用,因为服务帐户需要关联的YouTube频道,并且您无法将新频道或现有频道与服务帐户关联。如果使用服务帐户调用YouTube数据API,则错误类型设置为
unauthorized
且原因设置为
youtubeSignupRequired
的API服务器

此外,这里还有一篇摘自另一个地方的文章,再次说明了这一事实(下面的重点也是我的):

如果尝试使用OAuth 2.0服务帐户流,则通常会出现此错误。YouTube不支持服务帐户,如果您尝试使用服务帐户进行身份验证,则会出现此错误

我从中提取上述官方声明的上下文并不包含在您上面所示的上下文中。尽管如此,事实仍然存在

然而,另一段引语证实了上述事实,这一次是来自他们自己(下面的重点也是我的)