成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用 Python 監控 NASA TV 直播畫面

開發 后端
本文分享一個名為"Spacestills"的開源程序,它可以用于查看 NASA TV 的直播畫面(靜止幀)。

 本文分享一個名為"Spacestills"的開源程序,它可以用于查看 NASA TV 的直播畫面(靜止幀)。

演示地址:

https://replit.com/@PaoloAmoroso/spacestills

在Replit上運行的Spacestills主窗口

這是一個具有GUI的簡單系統,它訪問feed流并從Web下載數據。該程序僅需350行代碼,并依賴于一些開源的Python庫。

關于程序

Spacestills會定期從feed流中下載NASA TV靜止幀并將其顯示在GUI中。

該程序可以校正幀的縱橫比,并將其保存為PNG格式。它會自動下載最新的幀,并提供手動重新加載,禁用自動重新加載或更改下載頻率的選項。

Spacestillsis是一個比較初級的版本,但是它可以做一些有用的事情:捕獲并保存NASA TV直播的太空事件圖像。太空愛好者經常在社交網絡或論壇共享他們從NASA TV手動獲取的屏幕截圖。Spacestills節省了使用屏幕捕獲工具的時間,并保存了可供共享的圖像文件。您可以在Replit上在線運行Spacestills。

開發環境

筆者用Replit開發了Spacestills。Replit是云上的開發,部署和協作環境,它支持包括Python在內的數十種編程語言和框架。作為Chrome操作系統和云計算愛好者,筆者非常喜歡Replit,因為它可以在瀏覽器中完全正常運行,無需下載或安裝任何內容。

資源和依賴包

Spacestills依賴于一些外部資源和Python庫。

  •  NASA TV feed 流

肯尼迪航天中心的網站上有一個頁面,其中包含精選的NASA視頻流,包括NASA電視公共頻道。feed流顯示最新的靜止幀并自動更新。

每個feed都帶有三種尺寸的幀,Spacestills依賴于具有704x408像素幀的最大NASA TV feed流。最大更新頻率為每45秒一次。因此,檢索最新的靜止幀就像從feed流的URL下載JPEG圖像一樣簡單。

原始圖像被垂直拉伸,看起來很奇怪。因此,該程序可以通過壓縮圖像并生成未失真的16:9版本來校正縱橫比。

  •  Python

因PySimpleGUI的原因需要安裝 Python 3.6 版本。

  •  第三方庫

Pillow:圖像處理

PySimpleGUI:GUI框架(Spacestills使用Tkinter后端)

Request:HTTP請求

完整代碼 

  1. from io import BytesIO  
  2. from datetime import datetime, timedelta  
  3. from pathlib import Path  
  4. import requests  
  5. from requests.exceptions import Timeout  
  6. from PIL import Image  
  7. import PySimpleGUI as sg 
  8. FEED_URL = 'https://science.ksc.nasa.gov/shuttle/countdown/video/chan2large.jpg' 
  9. # Frame size without and with 16:9 aspect ratio correction  
  10. WIDTH = 704  
  11. HEIGHT = 480  
  12. HEIGHT_16_9 = 396 
  13. # Minimum, default, and maximum autoreload interval in seconds  
  14. MIN_DELTA = 45  
  15. DELTA = MIN_DELTA  
  16. MAX_DELTA = 300  
  17. class StillFrame():  
  18.     """Holds a still frame.  
  19.     The image is stored as a PNG PIL.Image and kept in PNG format.  
  20.     Attributes  
  21.     ----------  
  22.         image : PIL.Image  
  23.             A still frame  
  24.         original : PIL.Image  
  25.             Original frame with wchich the instance is initialized, cached in case of  
  26.             resizing to the original size  
  27.      Methods  
  28.     -------  
  29.         bytes : Return the raw bytes  
  30.         resize : Resize the screenshot  
  31.         new_size : Calculate new aspect ratio  
  32.     """ 
  33.     def __init__(self, image):  
  34.         """Convert the image to PNG and cache the converted original.  
  35.         Parameters  
  36.         ----------  
  37.             image : PIL.Image  
  38.                 Image to store  
  39.         """  
  40.         self.image = image  
  41.         self._topng()  
  42.         selfself.original = self.image  
  43.     def _topng(self):  
  44.         """Convert image format of frame to PNG.  
  45.         Returns  
  46.         -------  
  47.             StillFrame  
  48.                 Frame with image in PNG format  
  49.         """  
  50.         if not self.image.format == 'PNG':  
  51.             png_file = BytesIO()  
  52.             self.image.save(png_file, 'png')  
  53.             png_file.seek(0)  
  54.             png_image = Image.open(png_file)  
  55.             self.image = png_image  
  56.         return self 
  57.     def bytes(self):  
  58.         """Return raw bytes of a frame image.       
  59.          Returns  
  60.         -------  
  61.             bytes  
  62.                 Byte stream of the frame image  
  63.         """  
  64.         file = BytesIO()  
  65.         self.image.save(file, 'png')  
  66.         file.seek(0)  
  67.         return file.read()  
  68.     def new_size(self):  
  69.         """Return image size toggled between original and 16:9.      
  70.          Returns  
  71.         -------  
  72.             2-tuple  
  73.                 New size  
  74.         """  
  75.         size = self.image.size  
  76.         original_size = self.original.size  
  77.         new_size = (WIDTH, HEIGHT_16_9) if size == original_size else (WIDTH, HEIGHT)  
  78.         return new_size  
  79.     def resize(self, new_size):  
  80.         """Resize frame image.       
  81.          Parameters  
  82.         ----------  
  83.             new_size : 2-tuple  
  84.                 New size  
  85.         Returns  
  86.         -------  
  87.             StillFrame  
  88.                 Frame with image resized  
  89.         """  
  90.         if not(self.image.size == new_size):  
  91.             selfself.image = self.image.resize(new_size)  
  92.         return self 
  93. def make_blank_image(size=(WIDTH, HEIGHT)):  
  94.     """Create a blank image with a blue background.   
  95.      Parameters  
  96.     ----------  
  97.         size : 2-tuple  
  98.             Image size  
  99.      Returns  
  100.     -------  
  101.         PIL.Image  
  102.             Blank image  
  103.     """  
  104.     image = Image.new('RGB', sizesize=size, color='blue' 
  105.     return image  
  106. def download_image(url):  
  107.     """Download current NASA TV image.  
  108.     Parameters  
  109.     ----------  
  110.         url : str  
  111.             URL to download the image from   
  112.      Returns  
  113.     -------  
  114.         PIL.Image  
  115.             Downloaded image if no errors, otherwise blank image  
  116.     """  
  117.     try:  
  118.         response = requests.get(url, timeout=(0.5, 0.5))  
  119.         if response.status_code == 200:  
  120.             image = Image.open(BytesIO(response.content)) 
  121.         else:  
  122.             image = make_blank_image()  
  123.     except Timeout:  
  124.         image = make_blank_image()  
  125.     return image 
  126. def refresh(window, resize=Falsefeed=FEED_URL):  
  127.     """Display the latest still frame in window.    
  128.      Parameters  
  129.     ----------  
  130.         window : sg.Window  
  131.             Window to display the still to  
  132.         feed : string  
  133.             Feed URL    
  134.      Returns  
  135.     -------  
  136.         StillFrame  
  137.             Refreshed screenshot  
  138.     """  
  139.     still = StillFrame(download_image(feed))  
  140.     if resize:  
  141.         still = change_aspect_ratio(window, still, new_size=(WIDTH, HEIGHT_16_9))  
  142.     else:  
  143.         window['-IMAGE-'].update(data=still.bytes())  
  144.     return still  
  145. def change_aspect_ratio(window, still, new_size=(WIDTH, HEIGHT_16_9)):  
  146.     """Change the aspect ratio of the still displayed in window.  
  147.      Parameters  
  148.     ----------  
  149.         window : sg.Window  
  150.             Window containing the still  
  151.         new_size : 2-tuple  
  152.             New size of the still   
  153.      Returns  
  154.     -------  
  155.         StillFrame  
  156.             Frame containing the resized image  
  157.     """  
  158.     resized_still = still.resize(new_size)  
  159.     window['-IMAGE-'].update(data=resized_still.bytes())  
  160.     return resized_still  
  161. def save(still, path):  
  162.     """Save still to a file.  
  163.     Parameters  
  164.     ----------  
  165.         still : StillFrame  
  166.             Still to save  
  167.         path : string  
  168.             File name  
  169.      Returns  
  170.     -------  
  171.         Boolean  
  172.             True if file saved with no errors  
  173.     """  
  174.     filename = Path(path)  
  175.     try:  
  176.         with open(filename, 'wb') as file:  
  177.             file.write(still.bytes())  
  178.         saved = True  
  179.     except OSError:  
  180.         saved = False  
  181.     return saved  
  182. def next_timeout(delta):  
  183.     """Return the moment in time right now + delta seconds from now.  
  184.     Parameters  
  185.     ----------  
  186.         delta : int  
  187.             Time in seconds until the next timeout  
  188.      Returns  
  189.     -------  
  190.         datetime.datetime  
  191.             Moment in time of the next timeout  
  192.     """  
  193.     rightnow = datetime.now()  
  194.     return rightnow + timedelta(seconds=delta
  195. def timeout_due(next_timeout):  
  196.     """Return True if the next timeout is due.  
  197.     Parameters  
  198.     ----------  
  199.         next_timeout : datetime.datetime   
  200.      Returns  
  201.     -------  
  202.         bool  
  203.             True if the next timeout is due  
  204.     """  
  205.     rightnow = datetime.now()  
  206.     return rightnow >= next_timeout   
  207. def validate_delta(value):  
  208.     """Check if value is an int within the proper range for a time delta.  
  209.     Parameters  
  210.     ----------  
  211.         value : int  
  212.             Time in seconds until the next timeout    
  213.      Returns  
  214.     -------  
  215.         int  
  216.             Time in seconds until the next timeout  
  217.         bool  
  218.             True if the argument is a valid time delta  
  219.     """  
  220.     isinteger = False  
  221.     try:  
  222.         isinteger = type(int(value)) is int  
  223.     except Exception:  
  224.         delta = DELTA  
  225.     delta = int(value) if isinteger else delta  
  226.     isvalid = MIN_DELTA <= delta <= MAX_DELTA  
  227.     deltadelta = delta if isvalid else DELTA  
  228.     return delta, isinteger and isvalid  
  229. LAYOUT = [[sg.Image(key='-IMAGE-')],  
  230.           [sg.Checkbox('Correct aspect ratio', key='-RESIZE-'enable_events=True),  
  231.            sg.Button('Reload', key='-RELOAD-'),  
  232.            sg.Button('Save', key='-SAVE-'),  
  233.            sg.Exit()],  
  234.           [sg.Checkbox('Auto-reload every (seconds):', key='-AUTORELOAD-' 
  235.                        default=True),  
  236.            sg.Input(DELTA, key='-DELTA-'size=(3, 1), justification='right'),  
  237.            sg.Button('Set', key='-UPDATE_DELTA-')]]  
  238. def main(layout):  
  239.     """Run event loop."""  
  240.     window = sg.Window('Spacestills', layout, finalize=True 
  241.     current_still = refresh(window)  
  242.     delta = DELTA  
  243.     next_reload_time = datetime.now() + timedelta(seconds=delta 
  244.     while True:  
  245.         event, values = window.read(timeout=100 
  246.         if event in (sg.WIN_CLOSED, 'Exit'):  
  247.             break  
  248.         elif ((event == '-RELOAD-') or  
  249.                 (values['-AUTORELOAD-'] and timeout_due(next_reload_time))):  
  250.             current_still = refresh(window, values['-RESIZE-'])  
  251.             if values['-AUTORELOAD-']:  
  252.                 next_reload_time = next_timeout(delta)  
  253.         elif event == '-RESIZE-':  
  254.             current_still = change_aspect_ratio 
  255.                 window, current_still, current_still.new_size())  
  256.         elif event == '-SAVE-':  
  257.             filename = sg.popup_get_file(  
  258.                 'File name', file_types=[('PNG', '*.png')], save_as=True 
  259.                 title='Save image'default_extension='.png' 
  260.             if filename:  
  261.                 savesaved = save(current_still, filename)  
  262.                 if not saved:  
  263.                     sg.popup_ok('Error while saving file:', filename, title='Error' 
  264.         elif event == '-UPDATE_DELTA-':  
  265.             # The current cycle should complete at the already scheduled time. So  
  266.             # don't update next_reload_time yet because it'll be taken care of at the  
  267.             # next -AUTORELOAD- or -RELOAD- event.  
  268.             delta, valid = validate_delta(values['-DELTA-'])  
  269.             if not valid:  
  270.                 window['-DELTA-'].update(str(DELTA))  
  271.     window.close() 
  272.     del window  
  273. if __name__ == '__main__':  
  274.     main(LAYOUT)  

 

責任編輯:龐桂玉 來源: Python中文社區 (ID:python-china)
相關推薦

2015-06-30 17:41:31

戰旗TV

2013-02-01 10:09:46

TV客

2019-11-22 23:46:38

PythonNBAsh球員

2016-07-05 14:50:57

熊貓 領域

2021-06-04 10:31:41

PythonUniswap加密貨幣

2016-05-12 17:41:44

2016-05-17 20:57:43

2012-01-06 10:42:43

NASA開源

2022-03-24 14:42:19

Python編程語言

2020-12-09 11:53:24

鴻蒙開發HelloWord

2011-09-30 13:04:17

51CTO博客一周熱門監控網絡

2012-01-10 09:30:02

UbuntuCanonical

2023-04-09 23:17:16

Python監控城市空氣

2012-08-07 08:55:40

2020-01-13 07:42:01

技術研發指標

2011-05-31 16:14:26

Android

2015-01-27 15:30:10

反監控監控探測SnoopSnitch

2017-12-20 10:33:02

直播

2016-01-04 16:19:31

阿里云芒果TV云計算

2021-04-16 08:20:00

Flink CEP直播監控
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美video | 国产精品久久久久久久免费大片 | 天久久 | 91精品国产自产在线老师啪 | 中文字幕亚洲欧美日韩在线不卡 | 日韩一区二区三区四区五区 | 国产在线观看免费 | 亚洲最新在线视频 | 精品福利一区 | 一区二区三区四区在线视频 | 欧美日韩国产在线观看 | 国产一区二区三区不卡av | av香蕉 | 欧美激情国产日韩精品一区18 | 精品国产一区二区三区观看不卡 | 精品国产一二三区 | 日日射夜夜骑 | www.久久久久久久久久久久 | 国产一区二区精品 | 国产精品日产欧美久久久久 | 成人免费看电影 | 欧美成视频 | 欧美成人a∨高清免费观看 色999日韩 | 成人国产网站 | a级网站| 欧美狠狠操 | 在线一区二区三区 | 日本精品一区二区三区在线观看视频 | 国产精品久久久久久av公交车 | 中文字幕亚洲精品 | 日韩欧美电影在线 | 国产在线91| 婷婷色成人 | 999国产视频| 亚洲激情一区二区三区 | 欧美精品一区二区免费 | 男人天堂久久 | 日韩不卡视频在线观看 | 国产美女一区二区三区 | 淫片一级国产 | 天天操夜夜操 |