2016-06-11 4 views
0

Я пишу сценарий для загрузки видео с веб-сайта. Я добавил отчет, чтобы получить ход загрузки. Таким образом, на данный момент это показывает процент и размер загруженных данных. Я подумал, что было бы интересно добавить скорость скачивания и эта.
Проблема в том, что если я использую простой speed = chunk_size/time, то показанные скорости достаточно точны, но прыгают как сумасшедшие. Итак, я использовал историю времени, затраченную на загрузку отдельных кусков. Что-то вроде, speed = chunk_size*n/sum(n_time_history).
Теперь он показывает стабильную скорость загрузки, но это, безусловно, неправильно, потому что его значение составляет несколько бит/с, а загруженный файл заметно растет быстрее.
Может кто-нибудь сказать мне, где я ошибаюсь?Найти скорость загрузки для progressbar

Вот мой код.

def dlProgress(count, blockSize, totalSize): 
    global init_count 
    global time_history 
    try: 
     time_history.append(time.monotonic()) 
    except NameError: 
     time_history = [time.monotonic()] 
    try: 
     init_count 
    except NameError: 
     init_count = count 
    percent = count*blockSize*100/totalSize 
    dl, dlu = unitsize(count*blockSize)    #returns size in kB, MB, GB, etc. 
    tdl, tdlu = unitsize(totalSize) 
    count -= init_count        #because continuation of partial downloads is supported 
    if count > 0: 
     n = 5          #length of time history to consider 
     _count = n if count > n else count 
     time_history = time_history[-_count:] 
     time_diff = [i-j for i,j in zip(time_history[1:],time_history[:-1])] 
     speed = blockSize*_count/sum(time_diff) 
    else: speed = 0 
    n = int(percent//4) 
    try: 
     eta = format_time((totalSize-blockSize*(count+1))//speed) 
    except: 
     eta = '>1 day' 
    speed, speedu = unitsize(speed, True)   #returns speed in B/s, kB/s, MB/s, etc. 
    sys.stdout.write("\r" + percent + "% |" + "#"*n + " "*(25-n) + "| " + dl + dlu + "/" + tdl + tdlu + speed + speedu + eta) 
    sys.stdout.flush() 

Edit:
Исправлена ​​логика. Показанная скорость загрузки теперь намного лучше.
Поскольку я увеличиваю длину истории, используемой для расчета скорости, стабильность увеличивается, но внезапные изменения скорости (если загрузка останавливается и т. Д.) Не отображаются.
Как сделать его стабильным, но чувствительным к большим изменениям?

Я понимаю, что вопрос теперь более ориентирован на математику, но было бы здорово, если бы кто-нибудь мог помочь мне или указать мне в правильном направлении.
Кроме того, пожалуйста, скажите мне, есть ли более эффективный способ достичь этого.

+0

как насчет 'p = 30' и' speed = chunk_size * n/sum (n_time_history), если n

+0

@TomaszPlaskota Не то же самое, что и в моем коде? – SvbZ3r0

+0

мой плохой, просто смотрел на логику, которую вы описали. Поскольку вы уже это делаете, еще лучше оценить можно, сгруппировав таймфреймы (т. Е. 0-30,30-60,60-90 или желаемый промежуток времени), а затем разделив наименьшие/максимальные средние значения от этого набора и исчисляя приблизительное время без этих крайностей. Или используйте любой другой метод статистической фильтрации, а не min/max. Изменить: чтобы сделать его чувствительным к последним изменениям, вводите некоторый вес, который со временем уменьшается. –

ответ

1
_count = n if count > n else count 
time_history = time_history[-_count:] 
time_weights = list(range(1,len(time_history))) #just a simple linear weights 
time_diff = [(i-j)*k for i,j in zip(time_history[1:], time_history[:-1],time_weights)] 
speed = blockSize*(sum(time_weights))/sum(time_diff) 

Чтобы сделать его более стабильным и не реагирует, когда загрузить спайки вверх или вниз, вы могли бы добавить к этому, а также:

_count = n if count > n else count 
time_history = time_history[-_count:] 
time_history.remove(min(time_history)) 
time_history.remove(max(time_history)) 
time_weights = list(range(1, len(time_history))) #just a simple linear weights 
time_diff = [(i-j)*k for i,j in zip(time_history[1:], time_history[:-1],time_weights)] 
speed = blockSize*(sum(time_weights))/sum(time_diff) 

Это удалит самый высокий и самый низкий выброс в time_history который сделает номер отображается более стабильный. Если вы хотите быть придирчивым, вы, вероятно, можете сгенерировать весы перед удалением, а затем фильтровать сопоставленные значения с помощью time_diff.index(min(time_diff)).

Также использование нелинейных функций (например, sqrt()) для генерации веса даст вам лучшие результаты. О, и, как я сказал в комментариях: добавление статистических методов для фильтрации времени должно быть немного лучше, но я подозреваю, что это не стоит того, что он добавил бы.

+0

Спасибо большое! Я попробую, когда найду время. Кстати, в вашем коде есть ошибка. Это должно быть 'time_diff = [(ij) * k для i, j, k в zip (time_history [1:], time_history [: - 1], time_weights)] вместо' time_diff = [(ij) * time_weights [ i] для i, j в zip (time_history [1:], time_history [: - 1])] '. Потому что значения в 'time_history' не являются точно значениями индекса для' time_weights'. – SvbZ3r0

+0

И 'speed = blockSize * sum (time_weights)/sum (time_diff)', если моя математика правильная – SvbZ3r0

+0

ха-ха, вы, очевидно, правы, не должны писать ответы, когда у меня так много на голове, но это казалось забавным. Я слишком привык к индексам 'i',' j', 'k' и избегая их для реальных объектов. –

Смежные вопросы