使用Python在财政打印机上打印挂毯《权力的游戏》

有一次,在一个项目中,一位财务打印机落入我的手中。 我们每天在商店付款时都会遇到这些设备,但很少有人意识到它们的真实含义。 我不会详细介绍他们的工作,我只是说这些是在特殊热敏纸上打印带有购买数据的收据的东西(是的,几乎所有的财务打印机都没有墨水!)。

我必须弄清楚如何获得财务打印机的功能状态及其内部设置。 该任务早已完成,并且财务打印机在很远的地方被抛弃了很长时间……直到我有了重新创建一点的想法:D

此类打印机可让您打印单色图片。 当我有足够的印章,标志和同事的照片时,我决定挥舞着长长的挂毯,其依据是他们不断用“冬天临近”一词杀死某人

输出是这样的视频:


在下面的猫下用python打印挂毯的详细步骤。

在本文中,我将简要介绍一下该过程,并提供详细的注释,并假设输出将是具有一些实用技能的培训文章:

  • 从youtube下载挂毯视频
  • 创建长单色挂毯图像以在财务打印机上打印
  • 连接到财务打印机
  • 在财务打印机上打印挂毯
  • 我们将生成的视频剪辑安装在社交网络中以进行发布

从youtube下载挂毯视频


使用pytube库可以非常简单地完成此操作 ,您只需要确定要下载的视频流的索引即可。

从youtube下载视频的功能:
import time, pytube #         def load_bmp_from_video(video_url, filename): t1 = time.clock() #     video = pytube.YouTube(video_url) #        streams = video.streams.all() for stream in streams: print(stream) #       ,  18: 360p mp4 video.streams.get_by_itag(18).download("./", filename = filename ) t2 = time.clock() #      print('download done', t2-t1) #       got.mp4   360x640 load_bmp_from_video(video_url = 'https://www.youtube.com/watch?v=aZV4PclhHeA&', filename = 'got') 

当执行for stream in streams: print(stream)for stream in streams: print(stream)行时,我们会在控制台中看到视频中包含的所有视频流的列表:

 <Stream:itag =“ 22” mime_type =“视频/ mp4” res =“ 720p” fps =“ 30fps” vcodec =“ avc1.64001F” acodec =“ mp4a.40.2”>
 <Stream:itag =“ 43” mime_type =“视频/ webm” res =“ 360p” fps =“ 30fps” vcodec =“ vp8.0” acodec =“ vorbis”>
 <Stream:itag =“ 18” mime_type =“视频/ mp4” res =“ 360p” fps =“ 30fps” vcodec =“ avc1.42001E” acodec =“ mp4a.40.2”>
 <Stream:itag =“ 137” mime_type =“视频/ mp4” res =“ 1080p” fps =“ 30fps” vcodec =“ avc1.640028”>
 <Stream:itag =“ 248” mime_type =“视频/ webm” res =“ 1080p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 136” mime_type =“视频/ mp4” res =“ 720p” fps =“ 30fps” vcodec =“ avc1.4d401f”>
 <Stream:itag =“ 247” mime_type =“视频/ webm” res =“ 720p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 135” mime_type =“视频/ mp4” res =“ 480p” fps =“ 30fps” vcodec =“ avc1.4d401e”>
 <Stream:itag =“ 244” mime_type =“视频/ webm” res =“ 480p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 134” mime_type =“视频/ mp4” res =“ 360p” fps =“ 30fps” vcodec =“ avc1.4d401e”>
 <流:itag =“ 243” mime_type =“视频/ webm” res =“ 360p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 133” mime_type =“视频/ mp4” res =“ 240p” fps =“ 30fps” vcodec =“ avc1.4d4015”>
 <Stream:itag =“ 242” mime_type =“视频/ webm” res =“ 240p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 160” mime_type =“视频/ mp4” res =“ 144p” fps =“ 30fps” vcodec =“ avc1.4d400c”>
 <Stream:itag =“ 278” mime_type =“视频/ webm” res =“ 144p” fps =“ 30fps” vcodec =“ vp9”>
 <Stream:itag =“ 140” mime_type =“音频/ mp4” abr =“ 128kbps” acodec =“ mp4a.40.2”>
 <Stream:itag =“ 249” mime_type =“音频/ webm” abr =“ 50kbps” acodec =“ opus”>
 <Stream:itag =“ 250” mime_type =“音频/ webm” abr =“ 70kbps” acodec =“ opus”>
 <Stream:itag =“ 251” mime_type =“音频/ webm” abr =“ 160kbps” acodec =“ opus”>

我选择ID为18的线程是因为 这是一个很小的分辨率-我们仍然将其打印在检查磁带上,并且下载速度更快))

创建长单色挂毯图像以在财务打印机上打印


对于视频处理,我们需要著名的OpenCV库和Pillow(PIL的现代分支) (尽管在这里,可以使用libav工具中的avconv实用程序代替OpenCV,在本文的最后部分中对此进行详细介绍)。 非常感谢作者编写了python或python-opencv ,这是一个通过PIP安装的python轮子,不需要安装OpenCV本身( hooray! )。

财务打印机只能打印特殊图像-固定宽度为528像素的单色bmp文件(但长度不受限制,ho-ho-ho!)。 此外,视频剪辑中的挂毯图像一直在移动,因此我们需要仔细剪切帧,以便获得一张长照片。

所有这些都是通过以下功能完成的:
 import os, cv2, numpy as np from PIL import Image #            def save_frames_from_vide(filename): #          real_filename = filename.rsplit('.', 1)[0] #         for file in os.listdir('./'): if file.startswith('frame'): os.remove('./' + file) #         frames_list = [] vidcap = cv2.VideoCapture(filename) try: success, frame = vidcap.read() count = 1 while success: # and count < 500: #    #     1  100,     if count in [1, 100, 30945, 31000] or count % 370 == 0: #      (  ) mono_frame = frame if count == 370: mono_frame = mono_frame[0:mono_frame.shape[0], 172:mono_frame.shape[1]] if count == 30710: mono_frame = mono_frame[0:mono_frame.shape[0], 0:mono_frame.shape[1] - 200] mono_frame = mono_frame[20:-20, :] frames_list.append(mono_frame) print('read a new frame: ', success, count) success, frame = vidcap.read() count += 1 finally: vidcap.release() #     gobelin = np.concatenate((frames_list), axis = 1) #   -    cv2.imwrite('%s.png' % real_filename, gobelin) #        image = Image.open('%s.png' % real_filename) #  1        bmp fn = lambda x : 255 if x > 135 else 0 image = image.convert('L').point(fn, mode = '1') #       528  coef = 528. / image.height new_w = int(image.width * coef) new_h = int(image.height * coef) image = image.resize((new_w, new_h)) #    270         image = image.transpose(Image.ROTATE_270) image.save('%s_for_print.bmp' % real_filename) #       'got.png'  'got_for_print.bmp' save_frames_from_vide('got.mp4') 


在输出中,我们得到一张带有整个挂毯图像的长图像,下面仅显示一个片段,原始图像的宽度为55,000像素,并且根据发布规则未通过:



但是这样的图像是在单色转换后获得的,只有不旋转:



我们在财政打印机上打印挂毯


我可以使用Atol fprint-22型号的特定财务打印机,但一般规则适用于其他财务打印机型号。 此外,我的会计书非常古老,尚不支持FZ-54的新要求(我记得在该法律生效后,所有财务人员都必须通过OFD将数据发送给税务局,这会带来痛苦和痛苦-每个设备都会闪烁)。

关于财务打印机的一小部分题外话。 它们与POS设备有关-这是满足贸易需要的各种外围设备,它们连接到PC并集成到单个会计和支付系统中。 在这些知名设备中,您肯定已经看到了条形码扫描仪和信用卡支付终端。 对于所有这些设备,发明了统一的UnifiedPOS交互协议。

简而言之,这是一个单独的主题,涉及POS设备的专家圈子非常狭窄。 这些设备中的大多数都是专门为在Windows下通过COM对象操作而设计的,这种情况使情况变得复杂,因为dll文件的功能性文档描述很差。 尽管我听说过FreeBSD下运行的现金系统,但在使用POS设备时我还没有看到类似的东西,幸运的是,我并不需要详细地了解零售POS业务流程的世界...

因此,使用大多数这些设备的过程如下:

  • 驱动程序是从制造商安装的
  • 已配置通过制造商的实用程序与设备的连接
  • 用所需的设备寻找所需的注册表项
  • 寻找连接到它的必要设置
    (大多数工作在RS-232串行软件接口上)
  • 通过制造商驱动程序的COM对象连接到设备
  • 通过API COM对象使用设备
  • COM对象和设备物理端口已释放
    重点

由于我拥有一本古老的财务书,因此其驱动程序专门用于第8版。 现在,制造商添加了第10版的驱动程序,该驱动程序通过单独的python包装器模块大大简化了使用财务打印机的工作,这是个好消息。

以下代码演示了使用上述算法连接到财务打印机,产生蜂鸣声并打印先前获得的单色挂毯图像的功能。 我们将需要安装pywin32

结果证明代码很长而且很无聊,所以我把它放在了破坏者的下面:
 import win32com.client from _winreg import HKEY_CURRENT_USER, OpenKey, EnumValue #         class FiscallError(Exception) #     COM  , #  COM     def fiscal_print(filename): driver = None try: #      #         8.16. try: hKey = OpenKey(HKEY_CURRENT_USER, r"Software\Atol\Drivers\8.0\KKM\Devices") except Exception as err: raise FiscallError('      ' + '  ' + '   FPrint22-') #       , #       com  try: device_name,device_connect_params,device_connect_dt=EnumValue(hKey,0) except Exception as err: raise FiscallError('     ' + '     ' + '  FPrint22-') #       try: connect_dir = dict([tup.split(u'=') for tup in device_connect_params]) except Exception as err: raise FiscallError('     ' + '    FPrint22-') #    COM  try: driver = win32com.client.Dispatch("AddIn.FPrnM8") except Exception as err: raise FiscallError(' COM  AddIn.FPrnM8   ' + ' FPrint22-    , ' + '    ') #         add_code = driver.AddDevice() if driver.ResultCode != 0: raise FiscallError('     FPrint22-' + ' [ %s] - %s'% (driver.ResultCode, driver.ResultDescription)) #       COM  driver.Model = connect_dir['Model'] driver.PortNumber = connect_dir['PortNumber'] driver.UseAccessPassword = connect_dir['UseAccessPassword'] driver.DefaultPassword = connect_dir['UseAccessPassword'] driver.PortNumber = connect_dir['PortNumber'] driver.BaudRate = connect_dir['BaudRate'] #         #       COM  driver.DeviceEnabled = 1 #         GetStatus, #       . 61    v8.0 res = driver.GetStatus() if driver.ResultCode != 0: raise FiscallError('     FPrint22- ' + '[ %s] - %s' % (driver.ResultCode, driver.ResultDescription)) ###   #  ,       #   ,       driver.Beep() #  ,      (528) print('driver.PixelLineLength:', driver.PixelLineLength) # !!!       # (    COM ) driver.Alignment = 0 driver.LeftMargin = 0 driver.PrintPurpose = 1 driver.AutoSize = False driver.Scale = 100 #      driver.FileName = filename #    bmp  driver.PrintBitmapFromFile #        10  for i in range(10): driver.PrintString() #      driver.FullCut() # ! except FiscallError as err: raise err except Exception as err: raise FiscallError('    ' + '   FPrint22- - %s' % str(err)) finally: if driver: driver.DeviceEnabled = 0 fiscal_print('got_for_print.bmp') 


输出是这样的手稿,是《冰与火之歌》的表演:



打印机最终发出啸叫声,打印缓慢且暗淡,然后仅完成最终场景的完全打印-从未有一家财务打印机看到过这样的负载:D

它仍然是准备视频并将其发布到社交网络上。 作为一个音频系列,我在8bit网络上发现了一个业余作品-该系列的主题 。 想法是完全不使用视频编辑器而彼此叠加,我将在本文的最后部分对此进行介绍。

我们将生成的视频剪辑安装在社交网络中以进行发布


为此,有一个非常有用且功能强大的控制台工具可以代替整个视频编辑器-libav 。 它包括用于处理视频和音频文件的avconf和ffmpeg实用程序。 老实说,对我来说,这个工具是一个真正的发现,我向所有人推荐它!

安装的基本思路:

  • 从智能手机拍摄的视频开始和结束
    (以8位音乐适合mp3文件播放3次)
  • 将3个音频文件丢失写入一个文件
  • 将视频文件和音频文件覆盖到新的视频文件中
  • 将视频文件从mov格式转换为mp4格式
    (我的智能手机使用mov扩展名拍摄视频)

为此,我编写了一个在命令行上运行的脚本,该脚本可以在linux中的bash和win中的bat中执行(差异在脚本注释中指示):
 #     avconv -ss 00:00:10 -i got_print.mov -t 00:06:00 -c:v copy got_print_tmp.mov #      ( win) (echo file 'got_8bit.mp3' & echo file 'got_8bit.mp3' & echo file 'got_8bit.mp3') > list.txt #      ( linux) # cat list.txt # file 'got_8bit.mp3' # file 'got_8bit.mp3' # file 'got_8bit.mp3' #     3  ffmpeg -f concat -i list.txt -acodec copy got_8bit_3.mp3 #         avconv -i got_print_tmp.mov -i got_8bit_3.mp3 -c copy got_print_final.mov #       mp4 avconv -i got_print_final.mov -c:v libx264 got_print_final.mp4 #    (windows) del got_8bit_3.mp3 del got_print_tmp.mov #    (linux) # rm got_8bit_3.mp3 # rm got_print_tmp.mov 


就是这样,视频已创建:


PS:我的第一篇关于哈布雷的文章,打算写一篇简短的文章作为开始,我会尽力减少。)我希望阅读愉快,并且我的工作成果-很有趣)

Source: https://habr.com/ru/post/zh-CN465485/


All Articles