使用Video Intelligence API无法解析本地视频问题求助
咱们一步步拆解你的Video Intelligence API集成问题,看看为什么本地视频调用后没有返回结果:
1. 核心问题:错误的Base64编码处理
Google Cloud Video Intelligence API的setInputContent()接受的是原始视频二进制数据的ByteString,根本不需要先对视频文件做Base64编码!你现在的代码把原始视频字节转成了Base64,再传给API,这会导致API完全无法解析视频内容,自然不会返回任何结果。
修复起来很简单,直接去掉Base64编码步骤,用原始视频字节创建ByteString:
Path path = Paths.get(filePath); byte[] data = Files.readAllBytes(path); // 直接用原始字节创建ByteString,跳过Base64编码 ByteString videoBytes = ByteString.copyFrom(data); AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() .setInputContent(videoBytes) // 传入原始视频二进制数据 .addFeatures(Feature.LABEL_DETECTION) .build();
2. 异步操作重复调用的坑
你的代码里连续两次调用了response.get():
// 第一次调用get()获取结果 System.out.println(response.get().getAnnotationResultsList() + "Linha 83"); // 第二次又调用get() for (VideoAnnotationResults results : response.get().getAnnotationResultsList()) {
response.get()是阻塞方法,第一次调用已经完成了异步操作并返回结果,第二次再调用大概率会出问题——要么抛出异常,要么返回空列表。正确的做法是把结果先存到变量里,再重复使用:
System.out.println("Waiting for operation to complete..."); // 只调用一次get(),把结果存下来 AnnotateVideoResponse responseResult = response.get(); System.out.println("Annotation results: " + responseResult.getAnnotationResultsList()); // 用存好的结果遍历 for (VideoAnnotationResults results : responseResult.getAnnotationResultsList()) { // 后续处理逻辑不变 }
3. 补上错误捕获,别让异常“隐身”
现在的代码几乎没有错误处理逻辑,如果文件读失败、API调用超时或者权限不够,这些异常会直接抛出但没任何日志输出,你就会误以为是“无返回结果”。给代码加上完整的异常捕获,把错误信息打出来:
public void requisicaoVideo(String filePath) throws Exception { try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) { Path path = Paths.get(filePath); byte[] data = Files.readAllBytes(path); ByteString videoBytes = ByteString.copyFrom(data); AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder() .setInputContent(videoBytes) .addFeatures(Feature.LABEL_DETECTION) .build(); OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response = client.annotateVideoAsync(request); System.out.println("Waiting for operation to complete..."); AnnotateVideoResponse responseResult = response.get(); System.out.println("Annotation results: " + responseResult.getAnnotationResultsList()); for (VideoAnnotationResults results : responseResult.getAnnotationResultsList()) { System.out.println("Locations: "); for (LabelAnnotation labelAnnotation : results.getSegmentLabelAnnotationsList()) { System.out.println("Video label: " + labelAnnotation.getEntity().getDescription()); for (Entity categoryEntity : labelAnnotation.getCategoryEntitiesList()) { System.out.println("Video label category: " + categoryEntity.getDescription()); } for (LabelSegment segment : labelAnnotation.getSegmentsList()) { double startTime = segment.getSegment().getStartTimeOffset().getSeconds() + segment.getSegment().getStartTimeOffset().getNanos() / 1e9; double endTime = segment.getSegment().getEndTimeOffset().getSeconds() + segment.getSegment().getEndTimeOffset().getNanos() / 1e9; System.out.printf("Segment location: %.3f:%.2f\n", startTime, endTime); System.out.println("Confidence: " + segment.getConfidence()); } } } } catch (IOException e) { System.err.println("文件读取出错啦:" + e.getMessage()); e.printStackTrace(); } catch (InterruptedException | ExecutionException e) { System.err.println("API调用出错啦:" + e.getMessage()); e.printStackTrace(); } }
4. 最后检查文件路径和权限
确认你的程序能读取C:\\Users\\Web Designer\\Desktop\\Placas de Carros\\cat.mp4这个文件——比如有没有读取权限,文件是不是真的在这个路径下,路径里的空格有没有被正确处理(Windows里空格是允许的,但要确保没有打错字)。
额外小建议:大文件用GCS更稳定
如果你的视频文件比较大,直接传二进制数据可能会有性能问题,不如把视频上传到Google Cloud Storage,然后用setInputUri("gs://你的存储桶名称/视频路径.mp4")代替setInputContent(),这样调用API会更高效也更稳定。
内容的提问来源于stack exchange,提问作者Joao Demate

