Android、Ubuntu、およびPython:インターネットラジオ録音の自動化とOn-Airの同期

Habrコミュニティ全体にこんにちは!

確かに多くの人が「帰宅」<->「仕事」の途中で、Androidのバックグラウンドで音楽を聴いています。 また、10〜20分間、元気いっぱいの休憩時間に地下鉄をいっぱいにすることもよくあります。 運営拠点の場所への次の旅行で、すでに「昼食で百歳」であるトラックを楽しんで、夜に音楽ライブラリを更新したいという私の頭の中のメモを作りました。 もちろん、メモは営業日の旋風の中では安全に忘れられていました。翌朝、私は再びハッキングされたレコードで運転しました。 私はそれを少し考えて、自動化ビジネスへの私の重大な影響を排除するために、このプロセスを自動化する必要があると決めました。

関心のある市民-猫の下で歓迎。



戦略の選択は旅行中に決定されました。Atomの小さな「黒いco」サーバー(Ubuntuを搭載)のメリットは私の自由でした。 解決策は次のとおりです:悪魔の少女がサーバーでインターネットラジオのストリームをストリーミングし、ヘビのスクリプトが他のすべてを実行します:フォルダーをフォルダーに分類し、プレイリストを作成し、何らかの形ですべての良さをスマートフォンにマージします(できれば夜)。

一般概念の後、計画の特定の実装の選択がありました。 それでは、順番に始めましょう:



注意! すべての会話が記録されます。


放送ストリームを記録します。 「侵略者」として、私は小さなコンソールユーティリティstreamripperを選びました。 できること、必要なことすべて、さらにそれ以上。 ストリームのアドレスと、さらにいくつかの設定(トラックの保存場所と呼び出し方法)を彼女に与えるだけで十分です。



Pythonを使用する


私は自分の活動の性質上、ITインフラストラクチャに直接接続していません。 標準的なアクションの場合、スクリプトやハンドラーを作成する方が簡単な場合があり、落ち着いた良心でルーチンに費やすのではなく、主な仕事をします。 私はそれを我慢できません、突然、あなたが100個のアイテムをチェックし、供給者から納期を見つける必要があると判明したとき。 同時に、販売に心から関心を持ち、関心のあるベンダーであるベンダーは、21世紀には絶対に参入せず、サイト上のフォームの1つの位置に1つのフィールドを残します。 大量のクエリ処理とデータベースの同期? いいえ、彼らは聞きませんでした)これにより、1時間座って「コピーアンドペースト」を行うよりも、Apacheを取り上げてこの不名誉にカールを設定する方が簡単です。 何が良いかを見積もって、私は知識の荷物からpythonを選びました。 スケルトン全体がこれに基づいており、データ同期システムが構築されます。



Samba、FTP、またはSSHfs


次-情報をスマートフォンに転送する方法は? 一般的に、Android自体はnixのメガネット*であるため、転送インターフェースの選択に問題はないはずです。 Googleマーケットをすぐに確認したところ、Androidaのサーバー部分として必要なものがすべて見つかりました。 Samba、SSHfs、および標準FTPが利用可能であることが判明しました。 サーバーからandroidにテストを数回ダウンロードした後、2〜3 GBのトラックがFTPで停止しましたが、もちろんSSHfsで作業する方が快適でした。 しかし、それは不運です-私のスマート(Android HTC HD2と交換)が負荷に対処できなかったか、キー転送が不正に実装されたか、または何か他のものでしたが、実際、Sambaとsshの両方に堆積物がありました。 時々、特に大容量(0.7-1Gb以上)で記録の中断が発生したり、キーが失われたり、sshfsユーザーのアクセス権が誤って発行されたりしました。 一般に、安定したFTPを考えると、これが開発者のバグであろうと私の手であろうと、私は明らかに病気になり、最後の瞬間が残りました。 FTPサーバーは、サーバーからのコマンドまたは独自のスケジューラーによって電話で起動することになっています。 いずれにしても、Androidでコンソールを処理し、intent.actionをアプリケーションに渡してサーバーを起動する必要がありました。 そして、ここで失望は私を待っていました-クライアントのどれも(おそらく私は見栄えが悪いのですか?)AndroidManifest.xmlの説明に類似したものはありませんでした。 つまり アプリケーション自体の起動は可能でしたが、サーバーの起動-もはや。 幸運なことに、素晴らしいFTPServerアプリケーションの機能で、「選択したwi-fiネットワークに接続するときにFTPサーバーを起動する」などの機能に気づいたのです。 現在、この問題は解決されています。



Android


そして最後の質問。 これは、Androidオペレーティングシステム自体のデバイス、つまり消費電力が大きいことにより関連しています。 FTPサーバー自体は常にwi-fiとディスプレイを保持し、デバイスがこの方法でスリープ状態になるのを防ぎます。そうしないと、Androidがネットワークを切断し、FTPサーバーが利用できなくなります。 したがって、タスクは次のように要約されます:有料の場合、夜間および自宅のWi-Fiの範囲内にいるときにFTPを起動します。 HabréでTaskerプログラムについて読んだことがある記事を思い出しました。これは、さまざまな条件に応じて簡単なスクリプトの作成と電話機能の切り替えをサポートしていました。 プログラムはすぐにダウンロード、調査、テストされました。 結果は満足のいくものです。



まとめ


その結果、一般的に、バンドルは次のように動作しました。夜間(スマートフォンでスクリプトがサーバーで開始される数分前)にスマートフォンの側面から充電が行われ、ホームネットワークにアクセスできるようになると、FTPServerが起動し、ネットワーク上に2時間あり、その後電話が再起動しましたファイルライブラリを更新し、プレイリストを利用できるようにします。 Ubuntuサーバー側では、streamripperaを使用してストリームが記録され、クラウンを使用して、夜に以下を実行するスクリプトも起動されました。



このような小さなホームオートメーションは数週間私と一緒に暮らしており、これまで重大なバグはありませんでした。 朝起きてヘッドフォンをつけて、たくさんの新しい音楽があり、レコーディングを転送するプロセス全体が私としてバックグラウンドで行われていることを嬉しく思います。

実際、この小さな話は音楽に関するものではなく、日常生活ではなく創造性のための時間を残して、生活をより便利にするために現代の開発が私たちに与える機会についてのものです。



使用された「材料」:




PS


いくつかの推奨事項とコメント:



以下に、スクリプトのテキストを示します。一般的には非常に多くの説明がありますが、「オンザフライ」で明確になるはずです。

#!/usr/bin/python # -*- coding: utf-8 -*- #****************** ******************* #*********************************************************** import os import shutil from datetime import * import time from operator import itemgetter from ftplib import FTP import ftplib import subprocess import commands #*********************************************************** #****************** ******************* #****************** ************************ #*********************************************************** dir_exec = '' # ,         dir_music = '' #,      -(     streamripper) dir_music = os.path.join(dir_exec,dir_music) #    alias_dir = '' #   .  : '  - ..' time_shift = 3 #        time_sync = 4 # ,     time_storage = 30 # ,       server = '192.168.1.126' #FTP server,     login = '' # FTP pass_ftp = ' ' #  FTP port = '2121' # FTP andr_music = '/mnt/sdcard/Music' #   FTP rec_proc = ['streamripper', '  ', '-d', '-D', '%S/%A-%T'] #  streamrippera` #*********************************************************** #****************** ************************ #****************** ************************* #*********************************************************** #***     streamripper (    )      shell` def start_rec(proc_stream): num = commands.getoutput('pidof %s |wc -w' % proc_stream) if int(num) >= 2: os.system('killall ' + proc_stream) num = commands.getoutput('pidof %s |wc -w' % proc_stream) if int(num) == 0: proc = subprocess.Popen([rec_proc[0], rec_proc[1], rec_proc[2], dir_exec, rec_proc[3], rec_proc[4],], stdout=subprocess.PIPE) #***      ftp- def ftp_online(): ftpConnect = FTP() try: ftpConnect.connect(server,port) ftpConnect.login(login, pass_ftp) ftpConnect.quit() ftpConnect.close() enable = 1 except: enable = 0 return enable #***  ,   . def mdir(create_dir): if not os.path.isdir(create_dir): os.makedirs(create_dir) #***           def uniq_date(lst): return reduce(lambda y,z: not (z in y) and y.append(z) or y, lst, []) #***   mp3  def date_mp3(path_dir_music): out_date=[] names = os.listdir(path_dir_music) for name in names: if name.endswith('mp3'): path = os.path.join(path_dir_music,name) mtime = os.path.getmtime(path) - time_shift*60*60 out_date.append(date.fromtimestamp(mtime).strftime('%d.%m.%Y')) return out_date #***  mp3  def name_mp3(path_dir_music): out_name=[] names = os.listdir(path_dir_music) for name in names: if name.endswith('mp3'): out_name.append(name) return out_name #***  .          . def m3u(dir,path): m3u_n_d = [] m3u_n_s = [] m3u_names = name_mp3(path) i=0 for m3u_name in m3u_names: m3u_mtime = os.path.getmtime(os.path.join(path,m3u_name)) - time_shift*60*60 m3u_n_d.append([m3u_name,m3u_mtime]) i=i+1 m3u_n_d = sorted(m3u_n_d, key=itemgetter(1)) w = open(path+'/'+dir+'.m3u','w') w.write('#EXTM3U\n') #EXTM3U   m3U for i in range(i): #w.write('./'+m3u_n_d[i][0]+'\n') #   w.write(m3u_n_d[i][0]+'\n') #   PowerAmp w.close #***       NLST. def ftp_nlst(pwd): log = [] ftpConnect.cwd(pwd) ftpConnect.retrlines('NLST', callback=log.append) return log #***       LIST def ftp_list(pwd): log = [] file_ftp = [] ftpConnect.cwd(pwd) ftpConnect.retrlines('LIST', callback=log.append) files = (line.split(':')[1] for line in log) p = list(files) for name in p: file_ftp.append((name[3:])) return file_ftp #***          def num_day(dir_time): date_ = time.mktime(time.strptime(dir_time.split(' - ')[1],'%d.%m.%Y')) now_ = time.time() day_beet = (now_-date_)/(60*60*24) return int(day_beet) #*********************************************************** #****************** ************************* #****************** ***************************** #*********************************************************** #  start_rec(rec_proc[0]) #         creates_dirs = [] u_dates = uniq_date(date_mp3(dir_music)) j=0 for u_date in u_dates: mdir(os.path.join(dir_exec,alias_dir+u_date)) creates_dirs.append([alias_dir+u_date,os.path.join(dir_exec,alias_dir+u_date)]) j=j+1 #   mp3        out_names = name_mp3(dir_music) for out_name in out_names: path = os.path.join(dir_music,out_name) mtime = os.path.getmtime(path) - time_shift*60*60 out_date_temp = date.fromtimestamp(mtime).strftime('%d.%m.%Y') shutil.move(os.path.join(dir_music,out_name),os.path.join(dir_exec,alias_dir+out_date_temp,out_name)) #      for j in range(j): m3u(creates_dirs[j][0],creates_dirs[j][1]) #     dir_rem_serv = os.listdir(dir_exec) for dir_rem_s in dir_rem_serv: if dir_rem_s[:15] == alias_dir: if num_day(dir_rem_s) > time_storage: shutil.rmtree(os.path.join(dir_exec,dir_rem_s)) #     if ftp_online() == 1: ftpConnect = FTP() ftpConnect.connect(server,port) ftpConnect.login(login, pass_ftp) ftpConnect.cwd(andr_music) #      st = ftpConnect.pwd() #     dir_on_root = ftp_list(st) for dir_rem in dir_on_root: if dir_rem[:15] == alias_dir: if num_day(dir_rem) > time_sync: ftpConnect.cwd(os.path.join(st,dir_rem)) files_rem = ftp_list(os.path.join(st,dir_rem)) for file_rem in files_rem: ftpConnect.delete(file_rem) #      ftpConnect.cwd(st) ftpConnect.rmd(os.path.join(st,dir_rem)) #   ftpConnect.quit() ftpConnect.close() #    dir_names = os.listdir(dir_exec) for dir_name in dir_names: if dir_name[:15] == alias_dir: if num_day(dir_name) <= time_sync and ftp_online() == 1: ftpConnect = FTP() ftpConnect.connect(server,port) ftpConnect.login(login, pass_ftp) ftpConnect.cwd(andr_music) #      st = ftpConnect.pwd() #     dir_on_root = ftp_list(st) if dir_name not in dir_on_root: ftpConnect.mkd(os.path.join(st,dir_name)) ftpConnect.cwd(os.path.join(st,dir_name)) list_files = os.listdir(os.path.join(dir_exec,dir_name)) files_on_dir = ftp_list(os.path.join(st,dir_name)) for file in list_files: st_file = str(os.path.join(dir_exec,dir_name,file)) if file not in files_on_dir: ftpConnect.storbinary('STOR ' + file, open(st_file, 'rb'),1024) if file.endswith('m3u'): ftpConnect.storbinary('STOR ' + file, open(st_file, 'rb'),1024) ftpConnect.quit() ftpConnect.close() #*********************************************************** #****************** ******************************
      
      






All Articles