سؤال

أنا أعيش على الجانب الآخر من العالم من بيتي (GMT+1 الآن ، GMT+13 المنزل) ، أشتاق القديم الأرضية محطة إذاعية.وقد تيار شوتكاست, وأود أن مجرد تأخير ذلك قبل 12 ساعة بحيث يكون متاح دائما عندما أريد الاستماع إليها ، بطريقة من شأنها أن تجعل التوقيت تتم مزامنة التوقيت.

أتصور هذا البرنامج النصي التي يتم تشغيلها على الخادم المضيف.

ساذجة النهج سيكون ببساطة إلى تخصيص ما يكفي من ذاكرة الوصول العشوائي في ringbuffer لتخزين كامل 12 ساعة تأخير الأنابيب في الإخراج من streamripper.ولكن هو تيار 128kbps mp3, مما يعني (128/8) * 60 * 60 = ~56MB في الساعة ، أو 675MB طوال 12 ساعة العازلة التي ليس عملي جدا.بالإضافة إلى أنني قد تضطر إلى التعامل مع الخادم المضيف فقط قتل العملية بعد فترة معينة من المهلة.

إذا ، ما هي بعض الاستراتيجيات التي قد تكون في الواقع عملية ؟

هل كانت مفيدة؟

المحلول

تيار السفاح سيكون بطريقة سهلة و ربما في الطريق الصحيح, ولكن إذا كنت تريد أن تفعل ذلك مبرمج الطريقة....

  • معظم التنمية آلات قليلا جدا من ذاكرة الوصول العشوائي.هل أنت متأكد من أنك لا يمكن أن تدخر 675 MB ؟
  • بدلا من تخزين الناتج في منطقة عازلة لا يمكنك تخزينه في ملف أو ملفات(s), أقول ساعة في المرة الواحدة ؟ (أساسا ، سيكون من الكتابة الخاصة بك تيار السفاح)
  • تحويل التيار إلى انخفاض معدل البت ، إذا كنت يمكن أن يتسامح مع خسارة في الجودة

نصائح أخرى

لماذا لا فقط تحميل البرنامج مع الطاعن تيار مثل Ripshout أو شيء من هذا؟

وللإجابة على سؤالي الخاص، وهنا السيناريو الذي يبدأ العمل كمهمة كرون كل 30 دقيقة. انها مقالب الدفق الواردة في قطع مسافة 5 دقائق (أو مجموعة من FILE _ ثانية) إلى دليل معين. تتم مزامنة الحدود كتلة لعقارب الساعة، وأنها لا تبدأ الكتابة حتى نهاية من قطعة الزمنية الحالية، بحيث يمكن للتخصيص مواصفات المستعملين تشغيل تتداخل دون مضاعفة البيانات أو ترك الثغرات. تتم تسمية الملفات كما (وقت العصر عدد٪ الثواني في 24 ساعة) .str.

وأنا لم ارتكب لاعب حتى الآن، ولكن خطة لتعيين الدليل الإخراج إلى مكان ما على شبكة الانترنت يمكن الوصول إليها، وكتابة السيناريو ليتم تشغيلها محليا يستخدم نفس رمز حساب الطابع الزمني كما هنا لبالتسلسل وصول (الطابع الزمني قبل 12 ساعة) .str، تك لهم معا مرة أخرى، ثم قم بإعداد كخادم شوتكاست محليا. بعد ذلك فقط يمكن أن نشير مشغل الموسيقى الخاص بي في HTTP: // المضيف المحلي: ميناء وسهولة الحصول عليها

تحرير: نسخة جديدة مع مهلة وأفضل حالة خطأ التدقيق، بالإضافة إلى ملف السجل لطيفة. هذا قيد التشغيل حاليا خالية من عقبة في بلدي (رخيصة) الإستضافة المشتركة، مع أية مشاكل.

#!/usr/bin/python
import time
import urllib
import datetime
import os
import socket

# number of seconds for each file
FILE_SECONDS = 300

# run for 30 minutes
RUN_TIME = 60*30

# size in bytes of each read block
# 16384 = 1 second
BLOCK_SIZE = 16384

MAX_TIMEOUTS = 10

# where to save the files
OUTPUT_DIRECTORY = "dir/"
# URL for original stream
URL = "http://url/path:port"

debug = True
log = None
socket.setdefaulttimeout(10)

class DatestampedWriter:

    # output_path MUST have trailing '/'
    def __init__(self, output_path, run_seconds ):
        self.path = output_path
        self.file = None
        # needs to be -1 to avoid issue when 0 is a real timestamp
        self.curr_timestamp = -1
        self.running = False
        # don't start until the _end_ of the current time block
        # so calculate an initial timestamp as (now+FILE_SECONDS)
        self.initial_timestamp = self.CalcTimestamp( FILE_SECONDS )
        self.final_timestamp = self.CalcTimestamp( run_seconds )
        if debug:
            log = open(OUTPUT_DIRECTORY+"log_"+str(self.initial_timestamp)+".txt","w")
            log.write("initial timestamp "+str(self.initial_timestamp)+", final "+str(self.final_timestamp)+" (diff "+str(self.final_timestamp-self.initial_timestamp)+")\n")

        self.log = log

    def Shutdown(self):
        if self.file != None:
            self.file.close()

    # write out buf
    # returns True when we should stop
    def Write(self, buf):
        # check that we have the correct file open

        # get timestamp
        timestamp = self.CalcTimestamp()

        if not self.running :
            # should we start?
            if timestamp == self.initial_timestamp:
                if debug:
                    self.log.write( "starting running now\n" )
                    self.log.flush()
                self.running = True

        # should we open a new file?
        if self.running and timestamp != self.curr_timestamp:
            if debug:
                self.log.write( "new timestamp "+str(timestamp)+"\n" )
                self.log.flush()
            # close old file
            if ( self.file != None ):
                self.file.close()
            # time to stop?
            if ( self.curr_timestamp == self.final_timestamp ):
                if debug:
                    self.log.write( " -- time to stop\n" )
                    self.log.flush()
                self.running = False
                return True
            # open new file
            filename = self.path+str(timestamp)+".str"
            #if not os.path.exists(filename):
            self.file = open(filename, "w")
            self.curr_timestamp = int(timestamp)
            #else:
                # uh-oh
            #   if debug:
            #       self.log.write(" tried to open but failed, already there\n")
            #   self.running = False

        # now write bytes
        if self.running:
            #print("writing "+str(len(buf)))
            self.file.write( buf )

        return False

    def CalcTimestamp(self, seconds_offset=0):
        t = datetime.datetime.now()
        seconds = time.mktime(t.timetuple())+seconds_offset
        # FILE_SECONDS intervals, 24 hour days
        timestamp = seconds - ( seconds % FILE_SECONDS )
        timestamp = timestamp % 86400
        return int(timestamp)


writer = DatestampedWriter(OUTPUT_DIRECTORY, RUN_TIME)

writer_finished = False

# while been running for < (RUN_TIME + 5 minutes)
now = time.mktime(datetime.datetime.now().timetuple())
stop_time = now + RUN_TIME + 5*60
while not writer_finished and time.mktime(datetime.datetime.now().timetuple())<stop_time:

    now = time.mktime(datetime.datetime.now().timetuple())

    # open the stream
    if debug:
        writer.log.write("opening stream... "+str(now)+"/"+str(stop_time)+"\n")
        writer.log.flush()
    try:
        u = urllib.urlopen(URL)
    except socket.timeout:
        if debug:
            writer.log.write("timed out, sleeping 60 seconds\n")
            writer.log.flush()
        time.sleep(60)
        continue
    except IOError:
        if debug:
            writer.log.write("IOError, sleeping 60 seconds\n")
            writer.log.flush()
        time.sleep(60)
        continue
        # read 1 block of input
    buf = u.read(BLOCK_SIZE)

    timeouts = 0
    while len(buf) > 0 and not writer_finished and now<stop_time and timeouts<MAX_TIMEOUTS:
        # write to disc
        writer_finished = writer.Write(buf)

        # read 1 block of input
        try:
            buf = u.read(BLOCK_SIZE)
        except socket.timeout:
            # catch exception but do nothing about it
            if debug:
                writer.log.write("read timed out ("+str(timeouts)+")\n")
                writer.log.flush()
            timeouts = timeouts+1

        now = time.mktime(datetime.datetime.now().timetuple())
    # stream has closed,
    if debug:
        writer.log.write("read loop bailed out: timeouts "+str(timeouts)+", time "+str(now)+"\n")
        writer.log.flush()
    u.close();
    # sleep 1 second before trying to open the stream again
    time.sleep(1)

    now = time.mktime(datetime.datetime.now().timetuple())

writer.Shutdown()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top