You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
prolefeeder/prolefeeder.py

105 lines
3.5 KiB
Python

from flask import (Flask, render_template, flash, redirect,
url_for, request, send_from_directory)
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import DateTimeField, DecimalField, SubmitField
from wtforms.validators import DataRequired, NumberRange
from datetime import datetime, timedelta
import os
import random
import re
import subprocess
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
Bootstrap(app)
class DownloadForm(FlaskForm):
start_time = DateTimeField('Start time', validators=[DataRequired()], id='start_time')
length = DecimalField('Length', validators=[DataRequired(),
NumberRange(min=1, max=app.config['MAX_LENGTH'])])
submit = SubmitField('Download')
@app.route('/', methods=['GET', 'POST'])
def download():
form = DownloadForm()
if request.method == 'GET':
form.start_time.data = datetime.now().replace(minute=0, second=0) - timedelta(hours=1)
form.length.data = 60
elif form.validate_on_submit():
output_filename = prepare_download(form)
if output_filename:
flash('The download should start immediately.', 'success')
return render_template('download.html', form=form, filename=output_filename)
else:
flash('Error preparing download!', 'warning')
else:
flash('Error in form!', 'warning')
return render_template('download.html', form=form)
@app.route('/download_file/<path:filename>')
def download_file(filename):
return send_from_directory(app.config['DATA_DIR'], filename,
as_attachment=True)
def prepare_download(form):
"""Prepare a download given the user's request form"""
def start_time_for_source_fn(fn):
return datetime.strptime(fn, 'qfhi-%Y%m%d-%H%M.mp3')
def length_for_source_fn(fn):
size = os.stat(os.path.join(app.config['DATA_DIR'], fn)).st_size
length = timedelta(minutes=size / (1000*app.config['KBITS']/8) / 60)
return length
# Get a sorted list of all source files with start time and length
sources = []
for fn in os.listdir(app.config['DATA_DIR']):
try:
start_time = start_time_for_source_fn(fn)
length = length_for_source_fn(fn)
sources.append({'fn': fn, 'start_time': start_time, 'length': length})
except ValueError:
pass
sources = sorted(sources, key=lambda s: s['start_time'])
# Only interested in the source files from the start file
start_index = None
for i, source in enumerate(sources):
if source['start_time'] <= form.start_time.data < source['start_time'] + source['length']:
start_index = i
sources = sources[start_index:]
# Seek into the first file
ss = (form.start_time.data - sources[0]['start_time']).total_seconds()
# Let ffmpeg do the rest of the job
# XXX Necessary to limit the concat files?
output_filename = '{}_{}.mp3'.format(form.start_time.data, form.length.data)
c = ['ffmpeg', '-y']
c += ['-ss', str(ss)]
c += ['-i', 'concat:' + '|'.join([os.path.join(app.config['DATA_DIR'],
source['fn']) for source in sources])]
c += ['-codec', 'copy']
c += ['-t', str(form.length.data * 60)]
c += [os.path.join(app.config['DATA_DIR'], output_filename)]
app.logger.debug(' '.join(c))
subprocess.call(c)
return output_filename
if __name__ == '__main__':
app.run(debug=True)