找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

查看: 4780|回复: 5

[已回复] Python视频合成原理求解

1

主题

2

帖子

2

积分

贫民

积分
2
Hejs 发表于 2016-10-3 13:37:20 | 显示全部楼层 |阅读模式
小弟最近用爬虫爬取哔哩哔哩的视频,但是有些视频太大,视频经过分割,所以想请教一下怎样将分割的视频合成。视频是flv格式的。
回复

使用道具 举报

1419

主题

1891

帖子

291

积分

侠客

积分
291

最佳新人热心会员默默耕耘

whydo1 发表于 2016-10-3 18:48:34 | 显示全部楼层
网上拷贝来的,没试过,你自己试试. 论坛发链接的话,要审核,估计这两天版主们都过节去了.

从youku下载视频,总是分段的,非常麻烦去看,
折腾许久,搞出来这个,试试还没啥问题
flv的格式 http://osflash.org/flv#flv_format, 好像百度百科也有详细介绍,
大体上是
9字节 header + n个tag
每个tag的格式为:
4字节 上一个tag的size(上1个tag的data长度+11字节),
1字节 data format(video,audio之类),
3字节 data 长度,
3字节 timestamp(低bit位),
1字节 timestamp extented(高bit位),
3字节 保留,
data(长度为上面3字节)
不明白为啥每个独立的flv文件最后多出4字节为哪般,难道是youku的1个啥保留之类的?
  1. #-*- encoding: utf-8 -*-
  2. import binascii
  3. import sys,re,os
  4. # 第一个flv文件,取得最后的tagsize,赋于下一个flv,按最后的datalength复制给输出文件,得到总time_1
  5. # 从第二个flv文件起,去掉header部分后,timestamp对应的4个byte,加上之前的time_1,重新分配
  6. # 第二个flv文件也要取得最后的tagsize,赋于下一个flv,按最后的datalength复制给输出文件,最后总的time_2
  7. # 按此循环下去
  8. def splitdata(sf,outfh,lasttime,lasttagsize_hex):
  9.     # 取得一个flv文件, lasttagsize, lasttime,lastdataposition,
  10.     ts = open(sf,'rb').read()
  11.    
  12.     if lasttime == 0:
  13.         outfh.write(ts[:9])
  14.     #dp = 14
  15.     i = 9
  16.    
  17.     while i+5 < len(ts):
  18.         dp = i+5
  19.         if lasttagsize_hex:
  20.             outfh.write(binascii.a2b_hex(lasttagsize_hex)) # 4 byte tag size
  21.         else:
  22.             outfh.write(ts[dp-5:dp-1])
  23.         
  24.         outfh.write(ts[dp-1:dp+3])
  25.         #print "test:::",len(ts),dp,binascii.b2a_hex(ts[dp:dp+3])
  26.         tagdatalen = int(binascii.b2a_hex(ts[dp:dp+3]),16)
  27.         tp = dp+3
  28.         if lasttime == 0:
  29.             outfh.write(ts[dp+3:dp+7])
  30.         else: # 重新计算分配timestamp
  31.             oldtime = int(binascii.b2a_hex(ts[dp+6])+binascii.b2a_hex(ts[dp+3:dp+6]),16)
  32.             newtime_hex = hex(oldtime + lasttime)[2:].zfill(8)
  33.             outfh.write(binascii.a2b_hex(newtime_hex[2:]+newtime_hex[:2]))
  34.             
  35.         outfh.write(ts[dp+7:dp+10+tagdatalen])
  36.         
  37.         i = i + 15 + tagdatalen
  38.         #dp = dp+15+tagdatalen # 进入到下一个tag
  39.         
  40.     # 根据最后1个dp(dataposition),得到最后的lasttagsize, lasttime
  41.     lasttagtime = int(binascii.b2a_hex(ts[dp+6])+binascii.b2a_hex(ts[dp+3:dp+6]),16)
  42.     lasttagsize = int(binascii.b2a_hex(ts[dp:dp+3]),16)+11
  43.     lasttagsize_hex = hex(lasttagsize)[2:].zfill(8)
  44.     lasttime = lasttime + lasttagtime
  45.     print "%s has write, this time is %s, total time is %s, last tag size is %s(%s)" %(sf,lasttagtime,lasttime,lasttagsize,lasttagsize_hex)
  46.     return lasttime,lasttagsize_hex

  47. def main():
  48.     outfh = open('testout.flv','wb')
  49.     lasttime= 0
  50.     lasttagsize_hex = None
  51.    
  52.     flvlist = [
  53. '1.flv',
  54. '2.flv',
  55. '3.flv',
  56. '4.flv',
  57. '5.flv',
  58. '6.flv',
  59. '7.flv',
  60. '8.flv',
  61. '9.flv',
  62. '10.flv',
  63. '11.flv',
  64. '12.flv',
  65. '13.flv',
  66.     ]

  67.     for f in flvlist:
  68.         lasttime,lasttagsize_hex = splitdata(f,outfh,lasttime,lasttagsize_hex)
  69.            
  70.         
  71. if __name__ == '__main__':
  72.     main()
复制代码
回复 支持 反对

使用道具 举报

1419

主题

1891

帖子

291

积分

侠客

积分
291

最佳新人热心会员默默耕耘

whydo1 发表于 2016-10-3 18:50:51 | 显示全部楼层
网上拷贝来的,直接发链接需要审核. 估计这几天也没有人审核了.

从youku下载视频,总是分段的,非常麻烦去看,
折腾许久,搞出来这个,试试还没啥问题
flv的格式 , 好像百度百科也有详细介绍,
大体上是
9字节 header + n个tag
每个tag的格式为:
4字节 上一个tag的size(上1个tag的data长度+11字节),
1字节 data format(video,audio之类),
3字节 data 长度,
3字节 timestamp(低bit位),
1字节 timestamp extented(高bit位),
3字节 保留,
data(长度为上面3字节)
不明白为啥每个独立的flv文件最后多出4字节为哪般,难道是youku的1个啥保留之类的?
  1. #-*- encoding: utf-8 -*-
  2. import binascii
  3. import sys,re,os
  4. # 第一个flv文件,取得最后的tagsize,赋于下一个flv,按最后的datalength复制给输出文件,得到总time_1
  5. # 从第二个flv文件起,去掉header部分后,timestamp对应的4个byte,加上之前的time_1,重新分配
  6. # 第二个flv文件也要取得最后的tagsize,赋于下一个flv,按最后的datalength复制给输出文件,最后总的time_2
  7. # 按此循环下去
  8. def splitdata(sf,outfh,lasttime,lasttagsize_hex):
  9.     # 取得一个flv文件, lasttagsize, lasttime,lastdataposition,
  10.     ts = open(sf,'rb').read()
  11.    
  12.     if lasttime == 0:
  13.         outfh.write(ts[:9])
  14.     #dp = 14
  15.     i = 9
  16.    
  17.     while i+5 < len(ts):
  18.         dp = i+5
  19.         if lasttagsize_hex:
  20.             outfh.write(binascii.a2b_hex(lasttagsize_hex)) # 4 byte tag size
  21.         else:
  22.             outfh.write(ts[dp-5:dp-1])
  23.         
  24.         outfh.write(ts[dp-1:dp+3])
  25.         #print "test:::",len(ts),dp,binascii.b2a_hex(ts[dp:dp+3])
  26.         tagdatalen = int(binascii.b2a_hex(ts[dp:dp+3]),16)
  27.         tp = dp+3
  28.         if lasttime == 0:
  29.             outfh.write(ts[dp+3:dp+7])
  30.         else: # 重新计算分配timestamp
  31.             oldtime = int(binascii.b2a_hex(ts[dp+6])+binascii.b2a_hex(ts[dp+3:dp+6]),16)
  32.             newtime_hex = hex(oldtime + lasttime)[2:].zfill(8)
  33.             outfh.write(binascii.a2b_hex(newtime_hex[2:]+newtime_hex[:2]))
  34.             
  35.         outfh.write(ts[dp+7:dp+10+tagdatalen])
  36.         
  37.         i = i + 15 + tagdatalen
  38.         #dp = dp+15+tagdatalen # 进入到下一个tag
  39.         
  40.     # 根据最后1个dp(dataposition),得到最后的lasttagsize, lasttime
  41.     lasttagtime = int(binascii.b2a_hex(ts[dp+6])+binascii.b2a_hex(ts[dp+3:dp+6]),16)
  42.     lasttagsize = int(binascii.b2a_hex(ts[dp:dp+3]),16)+11
  43.     lasttagsize_hex = hex(lasttagsize)[2:].zfill(8)
  44.     lasttime = lasttime + lasttagtime
  45.     print "%s has write, this time is %s, total time is %s, last tag size is %s(%s)" %(sf,lasttagtime,lasttime,lasttagsize,lasttagsize_hex)
  46.     return lasttime,lasttagsize_hex

  47. def main():
  48.     outfh = open('testout.flv','wb')
  49.     lasttime= 0
  50.     lasttagsize_hex = None
  51.    
  52.     flvlist = [
  53. '1.flv',
  54. '2.flv',
  55. '3.flv',
  56. '4.flv',
  57. '5.flv',
  58. '6.flv',
  59. '7.flv',
  60. '8.flv',
  61. '9.flv',
  62. '10.flv',
  63. '11.flv',
  64. '12.flv',
  65. '13.flv',
  66.     ]

  67.     for f in flvlist:
  68.         lasttime,lasttagsize_hex = splitdata(f,outfh,lasttime,lasttagsize_hex)
  69.            
  70.         
  71. if __name__ == '__main__':
  72.     main()
复制代码
回复 支持 反对

使用道具 举报

1419

主题

1891

帖子

291

积分

侠客

积分
291

最佳新人热心会员默默耕耘

whydo1 发表于 2016-10-3 18:52:16 | 显示全部楼层
我没有试过, 你自己试试看. 也就是用二进制打开文件,掐头去尾拼在一起,然后再写到一个文件里这样的.
回复 支持 反对

使用道具 举报

1

主题

2

帖子

2

积分

贫民

积分
2
Hejs  楼主| 发表于 2016-10-8 14:38:20 | 显示全部楼层
whydo1 发表于 2016-10-3 18:52
我没有试过, 你自己试试看. 也就是用二进制打开文件,掐头去尾拼在一起,然后再写到一个文件里这样的. ...

太感谢您了。成功了。
回复 支持 反对

使用道具 举报

1419

主题

1891

帖子

291

积分

侠客

积分
291

最佳新人热心会员默默耕耘

whydo1 发表于 2016-10-8 18:57:27 | 显示全部楼层
祝贺祝贺!以后多交流.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表