Skip to content

Instantly share code, notes, and snippets.

@fffonion
Last active October 11, 2019 10:57
Show Gist options
  • Save fffonion/ef3669ac89a0d9c3c3f8 to your computer and use it in GitHub Desktop.
Save fffonion/ef3669ac89a0d9c3c3f8 to your computer and use it in GitHub Desktop.
youku kux -> mkv
#coding:utf-8
from __future__ import print_function
import os
import sys
import struct
import math
TAG_TYPE = {
18:'SCRIPT',
9:'VIDEO',
8:'AUDIO'
}
MKVMERGE_BINARY = r'D:\SOFT\Resource.Mod\_VIDEO\MKVToolNix\mkvmerge.exe'
YOUKU_DIR = r'z:\youku'
def _byte2ui24(byte):
if sys.version.startswith('2'):
_ = map(ord, byte)
else:
_ = byte
return (_[0] << 16) + (_[1] << 8) + _[2]
def grab(infile, outfile, buff_size = 0x200000, debug = True):
#flv format http://wuyuans.com/2012/08/flv-format/
_in = open(infile, 'rb')
_in.seek(0xe40000)
_out = None
idx = 0xe40000
cnt = 1
_ = b'\x00' * 11 # setup
while _:
if _ == b'\x00' * 11:
if _out:#not first
_out.close()
_out = None
idx = math.ceil(idx / 0x40000) * 0x40000 # block size 0x40000?
_in.seek(idx)
_h = _in.read(9 + 4)#header 9, pre tag size
if _h.strip(b'\x00') != '' and _h[:3] == b'FLV':#test header magic
_out = open(outfile[:-4] + '_%d.flv' % cnt, 'wb')
print('New flv(%dp) @0x%08X%s' % (cnt, idx, ' ' * 20))
_out.write(_h)
idx += 9 + 4
cnt += 1
#raw_input('>>>')
else:
tagtype, length = struct.unpack('b3s7x', _)
length = _byte2ui24(length)
if debug:
print('TAG:%6s 0x%06X @0x%08X-0x%08X%s' % (TAG_TYPE[tagtype], length, idx, idx + length + 4, '\b' * 42), end = '')
idx += length + 4
_ = _in.read(length + 4) #data, pre tag size
_out.write(_)
#next tag
_ = _in.read(11)
if _out:
_out.write(_)
idx += 11
_in.close()
#_out.close()# out is already closed
return cnt - 1
def make_mkv(fname, cnt, mkvmerge_bin = MKVMERGE_BINARY):
def _gen_track():
#"1:0:0:0,2:0:1:0,3:0:2:0,1:1:0:1,2:1:1:1,3:1:2:1"
track_1 = ','.join(['%d:0:%d:0' % (i, i - 1) for i in range(1, cnt)])
track_2 = ','.join(['%d:1:%d:1' % (i, i - 1) for i in range(1, cnt)])
return ','.join((track_1, track_2))
while True:
if not os.path.exists(mkvmerge_bin):
if not mkvmerge_bin.endswith('.exe'):
mkvmerge_bin = os.path.join(mkvmerge_bin, 'mkvmerge.exe')
continue
print('mkv merge binary not found')
return
break
cmd_line = '"%s" -o "%s.mkv" --forced-track 0:no --forced-track 1:no -a 1 -d 0 -S -T --no-global-tags --no-chapters ( "%s_1.flv" ) %s --track-order 0:0,0:1 --append-to %s' % (
mkvmerge_bin, fname[:-4],
fname[:-4],
' '.join(['-a 1 -d 0 -S -T --no-global-tags --no-chapters + ( "%s_%d.flv" )' % (
fname[:-4], i) for i in range(2, cnt + 1)]),#append
_gen_track())
#print(cmd_line)
#anti 输入行太长。
open('./_.bat', 'w').write(cmd_line + '\n')
os.system('_.bat')
#print(os.popen(cmd_line).read())
def cleanup(fname, cnt):
for i in range(1, cnt + 1):
os.remove("%s_%d.flv" % (fname[:-4], i))
def batch(ykdir):
if not os.path.exists(ykdir):
print('youku dir not found')
return
for f in os.listdir(ykdir):
if f.endswith('kux'):
targ = os.path.join(ykdir, f)[:-3] + 'flv'
#targ = targ.replace(' ', '_')
print('processing %s ------>' % f)
cnt = grab(os.path.join(ykdir, f), targ, debug = False)
if make_mkv(targ, cnt):
print('%s failed ++++++<' % f)
else:
print('%s done ------<' % f)
cleanup(targ, cnt)
if __name__ == "__main__":
#cnt = grab(r'Z:\youku\233.kux', r'z:\temp\whatever.flv', debug=False)
#print(make_mkv(r'z:\temp\whatever.flv', cnt))
if len(sys.argv) == 3:
YOUKU_DIR = sys.argv[1]
MKVMERGE_BINARY = sys.argv[2]
batch(YOUKU_DIR)
else:
print('Usage: kux-extract.py YOUKU_DIR MKVMERGE_BINARY')
@misaka00251
Copy link

AttributeError: 'NoneType' object has no attribute 'write'.

Is this Youku's fault?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment