Zoinkity

HVQMmerge

Nov 12th, 2019 (edited)
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.44 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. class HVQM2:
  5.     def __init__(self, header, records):
  6.         self.records = records
  7.         if isinstance(header[0], str):
  8.             self.version = header[0]
  9.         else:
  10.             self.version = header[0].decode().strip('\x00')
  11.         # Don't save filesize; recalc using method.
  12.         self.horz = header[1]
  13.         self.vert = header[2]
  14.         self.hdiff= header[3]
  15.         self.vdiff= header[4]
  16.         self.enc1 = header[5]
  17.         self.enc2 = header[6]
  18.         self.vrec_num = header[7]
  19.         self.framerate = header[8]
  20.         self.vrec_max = header[9]
  21.         self.req_packets = header[10]
  22.         self.audio = header[11]
  23.         self.channels = header[12]
  24.         self.bitwidth = header[13]
  25.         self.enc3 = header[14]
  26.         self.arec_num = header[15]
  27.         self.samplerate = header[16]
  28.         self.arec_max = header[17]
  29.  
  30.     def __str__(self):
  31.         # Framerate's probably wrong.
  32.         return f"{o.horz}x{o.vert} @ {o.framerate / 1000}fps, {o.channels} channels @ {o.samplerate}Hz"
  33.  
  34.     @classmethod
  35.     def frombytes(cls, data, offset=0):
  36.         import struct
  37.         header = struct.unpack_from(">16s4xHH4B4L4B3L", data, offset)
  38.         return cls(header, data[offset+60:])
  39.  
  40.     @property
  41.     def filesize(self):
  42.         return len(self.records) + 60
  43.  
  44.     def tobytes(self):
  45.         return self.__bytes__()
  46.  
  47.     def __bytes__(self):
  48.         import struct
  49.         a = [self.version.encode(), self.filesize, self.horz, self.vert,
  50.              self.hdiff, self.vdiff, self.enc1, self.enc2, self.vrec_num,
  51.              self.framerate, self.vrec_max, self.req_packets, self.audio,
  52.              self.channels, self.bitwidth, self.enc3, self.arec_num,
  53.              self.samplerate, self.arec_max]
  54.         header = struct.pack(">16sLHH4B4L4B3L", *a)
  55.         return b''.join((header, self.records))
  56.  
  57. def merge(file1, file2):
  58.     """Returns True if fixed fields from header appear to match."""
  59.     if file1.version != file2.version:
  60.         print("File version mismatch.")
  61.     elif file1.horz != file2.horz:
  62.         print("Width mismatch.")
  63.     elif file1.vert != file2.vert:
  64.         print("Height mismatch.")
  65.     elif file1.hdiff != file2.hdiff:
  66.         print("Horizontal sampling rate mismatch.")
  67.     elif file1.vdiff != file2.vdiff:
  68.         print("Vertical sampling rate mismatch.")
  69.     elif file1.enc1 != file2.enc1:
  70.         print("Unknown encoding parameter 1 mismatch.")
  71.     elif file1.enc2 != file2.enc2:
  72.         print("Unknown encoding parameter 2 mismatch.")
  73.     elif file1.framerate != file2.framerate:
  74.         print("Frame interval mismatch.")
  75.     elif file1.audio != file2.audio:
  76.         print("Audio format mismatch.")
  77.     elif file1.channels != file2.channels:
  78.         print("Different number of audio channels.")
  79.     elif file1.bitwidth != file2.bitwidth:
  80.         print("Audio sample size mismatch.")
  81.     elif file1.enc3 != file2.enc3:
  82.         print("Unknown encoding parameter 3 mismatch.")
  83.     elif file1.samplerate != file2.samplerate:
  84.         print("Audio sample rate mismatch.")
  85.     else:
  86.         # They match enough, so merge!
  87.         h = [file1.version, file1.horz, file1.vert, file1.hdiff, file1.vdiff, file1.enc1, file1.enc2]
  88.         h.append(file1.vrec_num + file2.vrec_num)
  89.         h.append(file1.framerate)
  90.         h.append(max(file1.vrec_max, file2.vrec_max))
  91.         h.append(max(file1.req_packets, file2.req_packets))
  92.         h.extend([file1.audio, file1.channels, file1.bitwidth, file1.enc3])
  93.         h.append(file1.arec_num + file2.arec_num)
  94.         h.append(file1.samplerate)
  95.         h.append(max(file1.arec_max, file2.arec_max))
  96.         return HVQM2(h, b''.join((file1.records, file2.records)))
  97.     return None
  98.  
  99. def main():
  100.     import argparse
  101.     parser = argparse.ArgumentParser(description="Merge several HVQM2 videos into one binary.")
  102.     parser.add_argument('out', type=str)
  103.     parser.add_argument('file1', type=str)
  104.     parser.add_argument('file_', type=str, nargs='+')
  105.     args = parser.parse_args()
  106.  
  107.     with open(args.file1, 'rb') as f:
  108.         o = HVQM2.frombytes(f.read())
  109.     for i in args.file_:
  110.         with open(i, 'rb') as f:
  111.             j = HVQM2.frombytes(f.read())
  112.         o = merge(o, j)
  113.         if o is None:
  114.             raise RuntimeError("HVQM2 files were not merged for some dumb reason.")
  115.     with open(args.out, 'wb') as f:
  116.         f.write(bytes(o))
  117.  
  118. if __name__ == '__main__':
  119.     main()
  120.  
Add Comment
Please, Sign In to add comment