Skip to content

Instantly share code, notes, and snippets.

@fffonion fffonion/youku-kux.py
Last active Oct 11, 2019

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

commented Oct 11, 2019

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
You can’t perform that action at this time.