📜 ⬆️ ⬇️

Convert and upload to YouTube

Good day!

So, let's begin. In the article I will describe a short project on django that converts / uploads videos to your YouTube channel.


A few words about the history of the problem ... I work in a small regional television company, which one wonderful day I wanted people to watch their content, not only sitting at blue screens, but also on YouTube . Because we have a broadcast server from Omneon, all materials are prepared in mov format, and the average weight of a 15 minute program is 3.5 GB. Filling a file of this size is tedious and stupid, it would be much more correct to convert videos to mp4 (for example) and upload them to YouTube on light ones (we don’t lose much of the quality from this). For example: 3.5 GB are compressed somewhere in 100 MB of acceptable quality.
')
The article does not claim to be the title of "discovery" and "breakthrough of the year"; it simply organizes known facts into convenient instructions.

1. Algorithm


For myself, I was guided by the following sequence of actions:

I also wanted to add some kind of logging, ala “who / when / what uploaded”.

2. What is needed?


I hope you have installed django, otherwise it is meaningless to read further. You will also need the following packages:


3. Putting it all together


I like it myself when you can see at least the corner of my eye, because here’s the final screenshot:


I will talk point by point from the very start.
First of all, we are launching a new project: django-admin.py startproject YTupload

In the new project, we immediately govern settings.py to fit our needs and add the following fields:
ENCODE_DIR_FROM = '/__________YT/' ENCODE_DIR_TO = os.path.join(ROOT,'file_out') #     ...        file_out    YT_LOGIN = 'login@gmail.com' #   YT YT_PASSWORD = 'password' #   YT 


Above, I "stuttered" about logging actions. For this we need the following model.
create the django-admin.py startapp control application
open models.py
 # -*- coding: utf-8 -*- from django.db import models from django.contrib.auth.models import User class Log(models.Model): filename = models.CharField(max_length=300) filesize = models.CharField(max_length=300) user = models.ForeignKey(User) created = models.DateTimeField() uploaded = models.DateTimeField(null=True, blank=True) link = models.CharField(max_length=300, blank=True) #youtube properties title = models.CharField(max_length=300) description = models.TextField() keywords = models.CharField(max_length=300) status = models.CharField(max_length=300, blank=True) class People(models.Model): login = models.OneToOneField(User, primary_key=True) name = models.CharField(max_length=200) 


go to views.py
 # -*- coding: utf-8 -*- from django.shortcuts import render_to_response from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.template import RequestContext from django.shortcuts import get_object_or_404, get_list_or_404 from django.contrib.auth import login, logout from django.contrib.auth.forms import AuthenticationForm from control.models import * import os, datetime, settings #    def LogStatus(l): try: return Log.objects.filter(filename=l)[0].status except: return None def index(request, template): if not request.user.is_authenticated(): return HttpResponseRedirect('/enter/') loglist = Log.objects.order_by('-id')[:10] #    listdir = os.listdir(settings.ENCODE_DIR_FROM) dictdir = [{'filename':None,'filesize':None, 'status':None} for i in range(len(listdir))] n = 0 for l in listdir: dictdir[n]['filename'] = l dictdir[n]['filesize'] = os.path.getsize(os.path.join(settings.ENCODE_DIR_FROM,l)) dictdir[n]['status'] = LogStatus(l) n+=1 #     if request.method == 'POST': filename = request.POST['filename'] filesize = request.POST['filesize'] title = request.POST['title'] description = request.POST['description'] keywords = request.POST['keywords'] #     ? if Log.objects.filter(filename=filename): return HttpResponse('already in query') else: #   Log,   "" l = Log(filename=filename, filesize=filesize, user=User.objects.filter(id=int(request.user.id))[0], created=datetime.datetime.now(), title=title, description=description, keywords=keywords, status='in query') l.save() return HttpResponseRedirect('/') return render_to_response(template, {'dictdir':dictdir, 'loglist':loglist,}) def exit(request): logout(request) return HttpResponseRedirect('/enter/') def enter(request, template): authform = AuthenticationForm() if request.user.is_authenticated(): return HttpResponseRedirect('/') if request.method == 'POST': authform = AuthenticationForm(data=request.POST) if authform.is_valid(): login(request, authform.get_user()) return HttpResponseRedirect('/') return render_to_response(template, {'authform': authform}) 


The code is not complicated (if necessary, it is ready to tell about it in more detail), the index function gives 2 lists: the first is what files are in the folder, the second is what files are already written to the log. The output of this function is visible in the screenshot above ... enter and exit is the simplest authentication.

Go ahead: urls.py
 from django.conf.urls.defaults import * from django.contrib import admin admin.autodiscover() import views, settings urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), (r'^$', views.index, {'template': 'index.html'}), (r'^enter/$', views.enter, {'template': 'enter.html'}), (r'^exit/$', views.exit), (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}), ) 

Everything is simple here. Logged in, uploaded!

The final chord is converting.py , which does all the work.
 # -*- coding: utf-8 -*- import settings, os, datetime os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' from control.models import * if Log.objects.filter(status='converting'): quit() else: try: file = Log.objects.filter(status='in query')[0] except: quit() file.status = 'converting' file.save() #    basename, extension = os.path.splitext(file.filename) newfilename = basename + '.flv' os.system('ffmpeg -i ' + os.path.join(settings.ENCODE_DIR_FROM, file.filename) + ' -ar 22050 -vb 1500kbits/s ' + os.path.join(settings.ENCODE_DIR_TO, newfilename)) file.status = 'uploading' file.save() os.system('youtube-upload --email=' + settings.YT_LOGIN + ' --password=' + settings.YT_PASSWORD + ' --title="' + file.title.encode('utf-8') + '" --description="' + file.description.encode('utf-8') + '" --category="News" --keywords="' + file.keywords.encode('utf-8') + '" ' + os.path.join(settings.ENCODE_DIR_TO, newfilename).encode("utf-8")) file.status = 'uploaded' file.uploaded = datetime.datetime.now() file.save() 


I run this script through crontab. The meaning is simple: we take the first file with the status “in query” (in the queue), convert (change the status to converting), load (change the status to uploading), download (status = uploaded).
crontab:
*/1 * * * * python /var/www/YTupload/converting.py &> /dev/null

Well, actually I donate the template html-code:
enter.html
 <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title> | YTUpload | 1vank1n.habrahabr.ru</title> <style type="text/css"> html, body { font-size: 14px; font-family: Georgia, "Times New Roman", Times, serif; height: 100%; width: 100%; margin: 0; padding: 0; } #table-center { height: 100%; width: 100%; } #form-auth { margin-bottom: 0px; margin-top: 0px; margin-right: auto; margin-left: auto; height: 100px; width: 330px; } #form-auth table td { padding: 5px; } #form-auth input { background-color: white; border-color: #cccccc; border-style: solid; border-width: 1px; padding: 5px; display: block; margin: 0 auto; } </style> </head> <body> <table id="table-center"> <tr><td> <form id="form-auth" action="" method="POST">{% csrf_token %} <table > {{ authform.as_table }} <input type="hidden" name="formname" value="auth"> </table> <input type="submit" value=""> </form> </td></tr> </table> </body> </html> 


index.html
 <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>YTUpload | 1vank1n.habrahabr.ru</title> <script type="text/javascript" src="/media/jquery-1.6.1.min.js"></script> <script type="text/javascript"> $(function(){ $('#choose_file a').click(function(){ $('#file_properties').fadeIn(); $('input[name="filename"]').attr('value', $(this).text()); $('input[name="filesize"]').attr('value', $(this).next('span').text()); }); }); </script> <style type="text/css"> body {width:1000px;margin:0 auto;position: relative;font-size:11pt;} #file_properties {display: none;} #choose_file {width: 490px; float: left; height: 500px; overflow-y: auto;} #loglist, #loglist table {width: 500px; float:right;} #loglist td {border: 1px solid #555;margin: 0;padding: 5px;} #exit {display: block; position: absolute; top:0; right:0; padding: 10px; background: #ddf; color: #000; text-decoration: none;} input, textarea, button {border: 1px solid #ccc; padding:5px;} </style> </head> <body> <a id="exit" href="/exit/"></a> <div id="loglist"> <h1></h1> <table cellpadding="0" cellspacing="0"> <tr> <td> </td> <td></td> <td></td> </tr> {% for l in loglist %} <tr> <td>{{ l.filename }}</td> <td>{{ l.filesize }}</td> <td>{{ l.status }}</td> </tr> {% endfor %} </table> </div> <div id="choose_file"> <h1>1.  :</h1> <p>      ,       (+,-,%,',",^,&)!!!</p> {% for d in dictdir %} <li>{% if not d.status %}<a value="{{ d.filename }}" href="#">{% endif %}{{ d.filename }}</a> | <span>{{ d.filesize|filesizeformat }}</span></li> {% endfor %} </div> <div style="height:10px;width:100%;clear:both;"></div> <div id="file_properties"> <h1>2.  :</h1> <table> <form method="post" name="uploadform"> <tr><td>:</td><td><input type="text" name="filename" readonly /> <input type="text" name="filesize" hidden></td></tr> <tr><td>:</td><td><input type="text" name="title" /></td></tr> <tr><td>:</td><td><textarea name="description"></textarea></td></tr> <!-- <tr><td>:</td><td><select></select></td></tr> --> <tr><td> :</td><td><input type="text" name="keywords" /></td></tr> <tr><td></td><td><input type="submit" value="3.   YouTube" /></td></tr> </table> </form> </div> </body> </html> 


4. Instead of the final


I hope it will help someone / save time / or just have fun. The variant presented by me can be improved (can I put it on github?), Thank God a lot of things can be corrected, for example, what kind of development do I see:


Thanks for attention!

PS code is far from perfect, it will be "polished". Thanks to Evgeny Bespaly for the optimization tips, be sure to use

UPD: project on github = https://github.com/1vank1n/YTupload/ , I will be glad to everyone who will help bring it to mind!

Source: https://habr.com/ru/post/124508/


All Articles