赞
踩
1、最近遇到个问题,做业务需要管理几个抖音账号,用抖音开放平台做分片上传视频,多次返回不合法参数id,提交工单之后给的回复没有任何参考价值。
2、例如视频文件按15M进行切片,调用分片上传初始化接口,获取一个upload-id,执行上传;我只上传第一个视频观察返回信息。第一次第一个切片执行上传,返回不合法参数id,继续执行第二个切片的上传,还是不合法参数id,之后的切片就不用考虑了;第二次执行切片上传,重新获取upload-id,上传第一切片,发现居然上传成功了,紧接着尝试上传其他切片,都能成功;第三次执行上传,重新获取upload-id,上传第一个切片,发现又成了不合法参数id,后续的其他切片都上传失败。
已解决
工单说明
同样的上传参数,39M的视频分片上传,15M+24M切分,第一次上传失败,20210810XXXXXXXXXXXXXXX4927233640,不合法的对象id,但是我再操作一次就能上传成功了,2021081XXXXXXXXXXXXXXX452192B2343BD;紧接着进行第三次上传,又出现了问题202108XXXXXXXXXXXX12059196332065FA;请问相同的文件,为什么能有成功的情况?不合法的对象id到底指的是什么?
2021年08月10日 21:32
您好,单片建议大小在20M以内,太大会导致传输不稳定
这工单的回复完全没有什么参考意义,等这个工单的处理就3天时间,期间一直不断尝试,一直也没有解决,失败的频率很高
1、尝试用10M大小的文件切片,偶然间右击查看文件属性,大小10M,占用空间12M,怀疑切片有问题。1024X1024X10,按这个大小进行文件切片,切出来的文件占用空间12M,采用其他的方法进行切片,1000X1000X10,这个大小进行分片。
2、nio的文件分片操作
fin = new FileInputStream(localFilePath + filename);
fcin = fin.getChannel();
long size = fcin.size();
//nio的文件大小最好不要使用file.length()
//size是文件的大小,计算得到要切分为几片,为保证最后一片要大于5M的要求,将剩余的大小加到最后一片上去
long partNum = size / partFileSize;
long remain = size % partFileSize;
long splitSize = partFileSize;
long finallySize = partFileSize + remain;
使用 buffer.flip();记性切片。最后一片带着remain
//ByteBuffer buffer = ByteBuffer.allocate((int) partFileSize); //15M一片 //int count = 1; //while (count <= partNum) { // buffer.clear(); // if (count == partNum) { // buffer = ByteBuffer.allocate((int) finallySize); // } // int flag = fcin.read(buffer); // if (flag == -1) { // break; // } // buffer.flip(); // fout = new FileOutputStream(localFilePath + count + filename); // fcout = fout.getChannel(); // fcout.write(buffer); // log.info("文件分片生成 共{}个 第{}个 文件名{}", partNum, count, localFilePath + count + filename); // count++; //}
后来我觉得 buffer.filp可能有问题,导致我分片的上传成功率非常低,换用transferTo
从开始位置开始切片,每次切splitSize的大小,最后一片切splitSize+remain
long startPoint = 0;
for (int i = 1; i <= partNum; i++) {
fout = new FileOutputStream(localFilePath + i + filename);
fcout = fout.getChannel();
if (i == partNum) {
splitSize = finallySize;
}
fcin.transferTo(startPoint, splitSize, fcout);
startPoint += splitSize;
fcout.close();
fout.close();
}
3、还有一个注意的点,就是文件的上传,开放平台写的是直接上传一个video的数组,其实不是数组,就是一个完整的文件outputStream.toByteArray。
先读到inputStream中,再到outputStream.toByteArray,输入输出使用不同的流,不然io就会觉得不安全,可能会给报错
log.info("开始上传第{}个文件 路径{}", i, localFilePath + i + filename);
inputStream = new FileInputStream(new File(localFilePath + i + filename));//与根据File类对象的所代表的实际文件建立链接创建fileInputStream对象
outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
String uploadRst = douYinHttpService.douYinFilePost(uploadUrl + i, i + filename, outStream.toByteArray());
请求头
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.valueOf(MediaType.MULTIPART_FORM_DATA_VALUE)); ContentDisposition co = ContentDisposition.builder("form-data").name(VIDEO).filename(filename).build(); headers.setContentDisposition(co); HttpHeaders videoHeader = new HttpHeaders(); videoHeader.setContentDispositionFormData(VIDEO, filename); ByteArrayResource bar = new ByteArrayResource(bytes); HttpEntity<ByteArrayResource> videoPart = new HttpEntity<>(bar, videoHeader); MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add(VIDEO, videoPart); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity(body, headers); log.info("douYinFilePost 抖音File POST请求 url {} 参数 {}", url, videoPart); String content = null; try { content = restTemplate.postForObject(new URI(url), requestEntity, String.class);
根据postman发送请求就能追到请求头是什么。
文件的分片上传其实是上传的一个视频文件,比如用手机录制两个视频,5M以上(分片的要求文件要在5M以上),第一次 part-num是1,将视频上传了,第二次part-num是2上传第二个视频文件,最后complete完成上传,这种情况他其实只识别到第一个视频文件,账号发布视频以后发现视频的长度还是第一个的长度。
为什么会造成这种情况呢,因为第一片的上传完成后有视频的长度信息和结束标记位,后面的不管你上传再多的分片,他还是只能识别到第一个,以后的就不管了。
使用文件切割后,观察生成的分片之后的文件就会发现,其实第一个分片,windows在预览的时候能看出来是个视频文件,打开播放的时候能播放,到一个时间点以后就不能播放了,视频的长度也是总视频长度;而其他分片的视频文件,发现根本不能预览,双击打开之后也提示文件损坏。
如图:第一个是切片之前,紧挨着的是切之后第一个能预览能播放。其他啥也不行。
换用1000100010这种切片方案,加nio的channel的transferTo方法,使用几个视频做切片测试,测试6个文件,其中5个能一次性就分片上传成功。最后一个分片之后多次上传都不成功。换1000100015这样进行切片,每片15M,一次上传成功。
后续引入重试机制,将发布不成功的视频按其他的分片大小进行切分,再次上传,写个次数限制,重试5次,多了实在还不行,上传失败的就给用户提示吧,我也没招了。
尝试了4天,最终按这种方案解决了上传失败率太高的问题,基本能达到上传一个成功一个,不过也不能避免上传失败的情况,大神有什么指教可以公众号联系我。
后续想把网站完善下,弄上回复框,算是定一个小目标
个人网站
http://www.51pro.top
公众号 含联系方式
1、0927考虑业务给发的视频都是高清的视频,一秒10M,码率高,思路一寻找视频是不是不标准的?
2、0928出现自己的视频也传不上去了,和高清没什么关系,非高清的视频只要切片都是不合法的对象id
3、0928出现一次上传成功,0929出现一次上传成功。其他出现不合法的对象ID,怀疑抖音接口有问题,毕竟自己的代码能上传成功。
4、0928、0929提交工单给提示uploadid需要自己encode一次。毕竟有上传成功的,怀疑抖音平台问题。
0927追视频问题,vlc播放器加mediaInfo软件看视频区别,达到了29M每秒。普通的视频几十KB每秒
0927追一天没发现视频有什么问题。晚上发非高清的视频,发现切片也会失败
0928所有视频只要出现分片上传都会失败,一整天上传尝试一百次其中一次出现成功,妈的这失败高达99%,
但是其中还有一次成功的啊,不怀疑自己的代码有问题。0929上午出现一次成功,更不怀疑自己代码有问题了。
0929工单信息
2021年09月27日 11:24
不合法的对象id 到底是什么id ???按10M大小进行切片 分片上传返回不合法的对象id uploadID 到底要不要自己encode? 能不能电话联系一下 XXXXXXXXXXXXXXXXXX
已关闭
查看
2021年09月27日 19:55
「工单回复」:
您好,uploadID encode一次即可
2021年09月28日 17:13
回复给「工单」:
logid 20210928170850010212070082390889A4 已经encode一次了 ,还是不行 为什么有的视频可以,高清的视频不可以呢 视频地址还是原来那个
图片链接:XXXXXXXXXX
2021年09月28日 17:22
回复给「工单」:
自己encode以后 能成功上传的视频都不能上传了 不加还能有成功的
2021年09月28日 17:23
回复给「工单」:
高清的视频 分片都不成功 不清晰的那种 分片都可以上传成功; 只要加上encode 全失败
2021年09月28日 17:23
回复给「工单」:
能不能技术人给打个电话
2021年09月28日 17:53
「工单回复」:
对于日志20210928170850010212070082390889A4,我们检查后发现,传入的upload_id被encode了两次,实际上只需encode一次即可
2021年09月28日 17:54
「工单回复」:
不主动encode 可以成功,就不要encode了,你使用的工具内部可能会自动帮你encode
2021年09月28日 17:54
「工单回复」:
高清视频上传不成功,请提供相应的logid
2021年09月28日 18:11
回复给「工单」:
20210928170850010212070082390889A4
2021年09月28日 18:14
「工单回复」:
你好20210928170850010212070082390889A4 这个是之前itemid encode两次导致出错的日志
2021年09月28日 18:27
回复给「工单」:
202109281824330101980671340F00654D
2021年09月28日 18:28
回复给「工单」:
这个logid呢 其实是直接拿的uploadid的返回值 看看这个是怎么回事
2021年09月28日 18:31
回复给「工单」:
logid:202109281824330101980671340F00654D logid:20210928182358010198066232370058B1 20210928182324010212026091290049B2 看看这三个的分片上传都失败了 是为什么
图片链接:XXXXXXXXXXXXXXXXXXXXX
2021年09月28日 18:35
回复给「工单」:
高清视频上传不成功logid : 2021092818323801020204808429013C35 202109281833200102040482303D0105B7 2021092818340301021216203212013FDE 202109281834460102121860185201BE88
2021年09月28日 18:51
「工单回复」:
你好,辛苦再提供下上传视频部分的代码,以及upload_id
2021年09月28日 19:07
回复给「工单」:
视频地址 https://test-pinpaiyunyingbop-lingxi.oss-cn-beijing.aliyuncs.com//spreaduatfile/images/20210928/15757420c3e9e6ae8350ce2a863796a6/56ed5d87-c606-eb10-6a0e-38ebe04a6789.mp4
2021年09月28日 19:07
回复给「工单」:
upload_id=@9VwC1+GVDss1K23yZdEvTM6v0zC8Nf2FPMAn/A3yKFQROPf10iLiLFIhgQby5DoKZq6NSUBH1aHz+2F7oSfViQ==
2021年09月28日 19:07
回复给「工单」:
“logid”:“202109281903490102120381024503F418”
2021年09月28日 19:08
回复给「工单」:
代码截图,代码是可以上传视频的 只是能偶然一次上传成功,99的概率上传失败
图片链接:XXXXXXXXXXX
2021年09月28日 19:09
回复给「工单」:
高清视频地址 https://test-pinpaiyunyingbop-lingxi.oss-cn-beijing.aliyuncs.com//spreaduatfile/images/20210928/9c364275ba85fa114633fdac022a7a07/f7ae3ce9-e446-57f3-2252-30a93c9be292.mp4
2021年09月28日 19:11
回复给「工单」:
高清视频的upload_id=@9VwC1+GVDss1K23yZdEvTM6o0TPsPfnQO5NxoAvwJ1QROPn91Hi3LAwhgQby5DoKH3Rt+cf0jIRPLoxgvuchKA==&part_number=1 “logid”:“2021092819101101021205920833049DCC”
2021年09月28日 19:14
回复给「工单」:
代码并不是说全部都不能上传成功 ,中间出现少次可以成功的,不过是99概率的失败
图片链接:XXXXXXXXXXXXXX
2021年09月28日 21:05
「工单回复」:
可以再提供下upload_id 部分的代码吗?包括给upload_id 做encode的操作的代码
2021年09月29日 08:01
回复给「工单」:
/video/part/init/ 直接用的这个接口的返回值data里面的upload_id
2021年09月29日 08:22
回复给「工单」:
这个uploadid是可以用的 如果encode之后就会变成两次encode,之前一直用的没问题,自从9.26以后,每次上传都失败,都是不合法的对象id,26-29号之间只有一次分片上传成功,9点半左右贴uppload_id的代码
2021年09月29日 09:39
回复给「工单」:
这个代码用了一个月了,一直是没有问题的,27号左右出现分片上传都失败,昨天就成功一次
图片链接:XXXXXXXXXXXX
2021年09月29日 09:40
回复给「工单」:
接口返回的uoloadid,直接使用,可以上传
2021年09月29日 09:53
回复给「工单」:
前天 昨天的所有分片上传 成功过一次 其他全部失败 都是这个不合法的对象id
2021年09月29日 10:25
回复给「工单」:
追问一句 开放平台在一周以内有更新吗 8月份到9月中旬都是能正常使用的,也申请了生产环境的应用,最近这三天突然发现分片上传出问题
2021年09月29日 15:44
「工单回复」:
最近几次的请求的upload_id中存在 出现问题,建议使用原生的方法,自己主动encode upload_id,再次尝试请求
2021年09月29日 17:13
回复给「工单」:
获取upload_id的返回值 就是分片上传使用的id,在一周之前是没有出现这个不合法对象id的问题,最近3天出现的这个问题。在没有encode的情况下,今天还成功过一次; urlencoder.encode(upload_id)之后,从来没有成功过。而且工单中回复的说encode了两遍;为什么不encode能成功过1次,而encode之后却完全没有成功过,工单还回复加了两次?
2021年09月29日 22:18
回复给「工单」:
解决了 restTemplete的post方法源码中有对url进行转码的操作,操作了最后两位的等号 关闭工单吧
1、工单一直提示是uploadid有问题,需要encode一次,尝试使用postman发送,一个月之前使用postman分片上传的时候,uploadid不需要encode就能上传成功,这次尝试高概率返回不合法的对象id,使用工具encode之后发现 居然上传成功了。
这个现象是完全超过认知,为什么以前不需要做的,都能上传成功,现在的都不行了?反而加密后竟然可以了。
2、继续代码中encode,尝试多次后,postman发动的encode uploadid之后的上传都能成功,可是代码中出现的encode之后的全部失败。
为什么
3、怀疑代码发送后出现其他操作给我转码了。查询发送请求的代码。跟请求,打断点。
发请求使用的是restTemplete,追进去看看
这里调用的是post直接传的url,而正好,抖音开放平台中的uploadid是url中的参数,往里追
最后发现这里对url进行了转码操作
url中含有uploadid 最后的两个等号转换了%3D,其他的东西没有转换,这导致我的参数就发生了变化。
4、我怎么去掉转码这一步操作呢?
//UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
//String content = restTemplate.postForObject(builder.build(false).toUri(), requestEntity, String.class);
第一种思路,这样尝试几次还是不行。
5、妈的 不用restTemplate了,自己写httpClient
bytes是read的子节流的数组 //public String originPost(String url, String filePath, String filename, byte[] bytes) throws Exception { // String result = ""; // CloseableHttpClient httpClient = HttpClients.createDefault(); // CloseableHttpResponse response = null; // try { // HttpPost post = new HttpPost(url); // //设置请求体 // //List<NameValuePair> content = new ArrayList<NameValuePair>(); // //content.add(new BasicNameValuePair("video", bytes.toString())); // //UrlEncodedFormEntity e = new UrlEncodedFormEntity(content, "UTF-8"); // //post.setEntity(e); // 我这里尝试了好几种设置请求头的方案,用了好几个entry,追了几个Entity的实现类,尝试好几次后均失败--------------------------------- // MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); // entityBuilder.addPart("video", new FileBody(new File("XXXXXXXXXXXXXXXXXXXXXXXXXXXX"))); // entityBuilder.setCharset(Charset.forName("UTF-8")).addBinaryBody("video", new FileInputStream(filePath), ContentType.MULTIPART_FORM_DATA, filename); // // post.setEntity(entityBuilder.build()); // //设置请求头 // post.addHeader("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE); // post.addHeader("Content-Disposition", "name=\"video\"; filename=" + filename); // // //发送请求 // response = httpClient.execute(post); // if (response != null && response.getStatusLine().getStatusCode() == 200) { // org.apache.http.HttpEntity entity = response.getEntity(); // result = EntityUtils.toString(entity); // } // } catch (Exception e) { // log.info("originPost", e.getMessage()); // }
这几个写法一直返回的是系统正忙,请稍后再试,总觉得是自己的请求不对,请求头的参数没设置好。
心情实在是糟糕透了,很长时间没有弄好这个请求头,废了很长时间,都没整好,tcp http没学好,回去再自学去吧,不会写了。放弃。
如果有谁能把这个方法补充上也能发送成功。
后续哪位高手看见补上给留言,感激不尽
还是使用restTemplate,尝试一下这个方案,找post的重载的方法,看看有没有不转码的方法。看到一个这个,传URI,不会转码
content = restTemplate.postForObject(new URI(url), requestEntity, String.class);
皆大欢喜!!! 成功
后续创建视频也是使用这个encode之后的uploadid,还是用URI,不让他转码,自己手动转。
增加失败重试机制,多试几次,单次切片保持一个大小,多次切片的大小不同,第一次每片10M,第二次每片12M,依次涨点,最后还要保证最后一片的大小大于5M。
最后再来一次托底的操作,最后一次尝试如果小于100M,使用一次单片上传。大于100M最后一次尝试切片。
private static final Map<Integer, Long> redoCountPartSizeMap = new HashMap<>();
static {
redoCountPartSizeMap.put(1, 1000 * 1000 * 10L);
redoCountPartSizeMap.put(2, 1000 * 1000 * 12L);
redoCountPartSizeMap.put(3, 1000 * 1000 * 13L);
redoCountPartSizeMap.put(4, 1000 * 1000 * 14L);
redoCountPartSizeMap.put(5, 1000 * 1000 * 15L);
redoCountPartSizeMap.put(6, 1000 * 1000 * 18L);
}
网络的文件下载到本地
本地文件切片
获取uploadid
encode操作
分片上传,注意不能让http给转码
完成上传
创建视频。
2021-11-20
后续又来了
几天前发现有几个视频一直在请求审核状态,发现抖音平台视频状态细化了,从11.15以后状态码和之前的对不起来了,导致一直在请求审核状态。
看开放平台video_status i32 表示视频状态。1:细化为5、6、7三种状态;2:不适宜公开;4:审核中;5:公开视频;6:好友可见;7:私密视频
怎么看都怀疑是之前提交的一个工单 审核结束但返回状态是审核中的问题
再改改代码走起
2022-02-10
java.lang.OutOfMemoryError: Java heap space
问题代码和报错不贴了,涉密。。。。。
过完年刚回来,公司业务推广,不知道哪个楼盘活动推广加城市宣传片,点击发送以后,后台收到短信报异常,紧接着SLB异常报警,APM监控报警!!!!!!!!!
事态紧急,手机上收到各种报警,4台服务器有2台AMP监控超时,网关下掉服务器通知,幸亏是晚上10点多没多少人用,抓紧devops流水线重启,网关重新上线。
业务上传视频文件发送到多个抖音账号,抖音开放平台限制单个文件大小4G,业务人员不知道从哪里弄了一个3.5G大小的视频文件,正好他手底下有10个账号权限,点了全选,一下发到了10个账号上去,后面4台服务器收到队列消息,直接就开始下载文件处理,其中两台正好文件下载了3遍,在做文件切割的时候出现内存溢出。
业务没有强制需求做账号多选,产品出了多选发布的功能,我后台开发没对账号上锁做单步,三方都有问题,一起把问题背了下来。
1、首先考虑到是OOM异常,日志里的异常信息打到了lamdba表达式里面,没有具体的行数。既然是内存小,先考虑heap溢出用Xmx扩大一下,发现原来设置过这个参数,不让我们自己调整,换G1垃圾回收器,-XX:+UseG1GC。
大对象直接在堆里面了,那我不区分新生代和老年代不行吗,G1里面新生代和老年代他自己转,用G1总比用PS+PO强一点吧。
2、正好业务选了10个账号,要是再来两个,后台4个服务器都得被干死。这么大的文件,多来几个谁也受不了,加分布式锁。
消息来之后先加锁。获取不到锁的去延时队列,延迟个1min再消费;redis先锁视频文件id,再锁账号id,虽然大视频发的慢点,保证服务器死不了就行。
3、拆开lamdba,防止自己生成那么多的class不好追踪。增加各种日志打印。第二天紧急发版。
幸亏是年后出现的问题,要是年前,不堪设想啊。。。
产品、业务、开发、测试 这些人关系够铁,有问题大家一起扛,欣慰。
以后要特别注意这种大文件的处理,还同时处理多个,想想都后怕,万一所有服务器都干趴了,就不是这个结果了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。