-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathmkvcat.py
executable file
·105 lines (87 loc) · 3.63 KB
/
mkvcat.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python
import mkvparse
import sys
import traceback
import binascii
import os
import io
import mkvgen
def pstderr(*args):
#if sys.version < '3':
sys.stderr.write(str(args[0])+"\n")
#else:
# print(file=sys.stderr, *args)
class MatroskaConcatenator(mkvparse.MatroskaHandler):
def __init__(self, f):
self.f = f
self.prev_uuid = None
self.cur_uuid = os.urandom(16)
self.next_uuid = os.urandom(16)
self.headerpart = None
self.info_section_size = None
def tracks_available(self):
pstderr(" Tracks info:")
try:
for k in self.tracks:
t=self.tracks[k]
pstderr(" %d %s %s"%(k, t['type'][1], t['CodecID'][1]))
except:
pstderr(" can't print")
def segment_info_available(self):
pstderr(" Segment info:")
try:
for (k,(t_,v)) in self.segment_info:
if t_ == mkvparse.EbmlElementType.BINARY: v = binascii.hexlify(v)
pstderr(" %s: %s"%(k,v))
except:
pstderr(" can't print")
def frame(self, track_id, timestamp, data, more_laced_frames, duration, keyframe, invisible, discardable):
pass
def before_handling_an_element(self):
self.headerpart = self.fin.peek(100)
self.headerpart = self.fin.peek(100)
pstderr("peeked %d bytes"%(len(self.headerpart)))
pass
def begin_handling_ebml_element(self, id_, name, type_, headersize, datasize):
pstderr(" %s %d(%s) %d"%(name, headersize, binascii.hexlify(self.headerpart[:headersize]), datasize))
if name=="EBML": return type_
elif name=="Segment":
remainingfilesize = self.currentfilesize - self.fin.tell()
pstderr(" remaining file size: %d segment data size: %s"%(remainingfilesize, str(datasize)))
if datasize <= 0 and remainingfilesize > 0:
datasize = remainingfilesize
pstderr(" fixed segment size based on file size")
self.f.write(mkvgen.ebml_element(0x18538067,"",datasize)) # Segment header with known length
return mkvparse.EbmlElementType.JUST_GO_ON
#elif name=="Info":
# self.info_section_size = datasize
# return mkvparse.EbmlElementType.JUST_GO_ON
self.headersize = headersize
return mkvparse.EbmlElementType.BINARY
def ebml_top_element(self, id_, name, type_, data):
#pstderr(" %s %d %d"%(name, headersize, data))
if name=="EBML": return
elif name=="Segment": return
#elif name=="Info": return
#elif name=="SeekHead": return # invalidated by changing the Info
#pstderr("type:"+str(type(data)))
# just copy this element to output
#header = self.headerpart [ : self.headersize];
#pstderr("writing header: %s at %s; data len: %d"%(binascii.hexlify(header), self.f.tell(), len(data)))
#self.f.write(header)
#self.f.write(data)
self.f.write(mkvgen.ebml_element(id_,data))
if __name__ == '__main__':
if sys.version >= '3':
sys.stdout = sys.stdout.detach()
mkvgen.write_ebml_header(sys.stdout, "matroska", 2, 2)
concat = MatroskaConcatenator(sys.stdout)
for i in sys.argv[1:]:
pstderr("Opening %s" % i);
with io.open(i,"rb", buffering=True) as f:
try:
concat.fin = f
concat.currentfilesize = os.path.getsize(i)
mkvparse.mkvparse(concat.fin, concat)
except:
traceback.print_exc()