在存储视频之前,我可以使用ffmpeg转换从表单上传的Django视频吗?

2024-04-26 03:43:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我在尝试使用ffmpeg将用户上传的视频转换成flv已经有好几个星期了。我使用heroku托管我的网站,并使用s3boto将静态和媒体文件存储在amazons3上。初始的视频文件可以上传,但是当我检索视频并运行一个celery任务(在上传初始视频文件的同一个视图中),新文件不会存储在S3上。一个多月来,我一直在尝试让它工作,但运气不好,而且确实没有好的资源来学习如何做到这一点,所以我想如果我能在存储视频之前运行ffmpeg任务,我也许可以让它工作。不幸的是,我对python(或django)还不是很在行,所以我甚至不知道这是否/如何可能。有人有什么想法吗?我愿意在这一点上使用任何解决方案,不管有多难看,只要它成功地上传视频并使用ffmpeg转换成flv,结果文件存储在S3上。我的情况似乎并不常见,因为无论我在哪里寻找,我都找不到一个能解释我应该做什么的解决方案。因此,我将非常感谢任何指导。谢谢。我的相关代码如下:

#models.py
def content_file_name(instance, filename):
    ext = filename.split('.')[-1]
    new_file_name = "remove%s.%s" % (uuid.uuid4(), ext)
    return '/'.join(['videos', instance.teacher.username, new_file_name])

class BroadcastUpload(models.Model):
    title = models.CharField(max_length=50, verbose_name=_('Title'))
    description = models.TextField(max_length=100, verbose_name=_('Description'))
    teacher = models.ForeignKey(User, null=True, blank=True, related_name='teacher')
    created_date = models.DateTimeField(auto_now_add=True)
    video_upload = models.FileField(upload_to=content_file_name)
    flvfilename = models.CharField(max_length=100, null=True, blank=True)
    videothumbnail = models.CharField(max_length=100, null=True, blank=True)

#tasks.py
@task(name='celeryfiles.tasks.convert_flv')
def convert_flv(video_id):
    video = BroadcastUpload.objects.get(pk=video_id)
    print "ID: %s" % video.id
    id = video.id
    print "VIDEO NAME: %s" % video.video_upload.name
    teacher = video.teacher
    print "TEACHER: %s" % teacher
    filename = video.video_upload
    sourcefile = "%s%s" % (settings.MEDIA_URL, filename)
    vidfilename = "%s_%s.flv" % (teacher, video.id)
    targetfile = "%svideos/flv/%s" % (settings.MEDIA_URL, vidfilename)
    ffmpeg = "ffmpeg -i %s %s" % (sourcefile, vidfilename)
    try:
        ffmpegresult = subprocess.call(ffmpeg)
        #also tried separately with following line:
        #ffmpegresult = commands.getoutput(ffmpeg)
        print "---------------FFMPEG---------------"
        print "FFMPEGRESULT: %s" % ffmpegresult
    except Exception as e:
        ffmpegresult = None
        print("Failed to convert video file %s to %s" % (sourcefile, targetfile))
        print(traceback.format_exc())
    video.flvfilename = vidfilename
    video.save()

@task(name='celeryfiles.tasks.ffmpeg_image')        
def ffmpeg_image(video_id):
    video = BroadcastUpload.objects.get(pk=video_id)
    print "ID: %s" %video.id
    id = video.id
    print "VIDEO NAME: %s" % video.video_upload.name
    teacher = video.teacher
    print "TEACHER: %s" % teacher
    filename = video.video_upload
    sourcefile = "%s%s" % (settings.MEDIA_URL, filename)
    imagefilename = "%s_%s.png" % (teacher, video.id)
    thumbnailfilename = "%svideos/flv/%s" % (settings.MEDIA_URL, thumbnailfilename)
    grabimage = "ffmpeg -y -i %s -vframes 1 -ss 00:00:02 -an -vcodec png -f rawvideo -s 320x240 %s" % (sourcefile, thumbnailfilename)
    try:        
         videothumbnail = subprocess.call(grabimage)
         #also tried separately following line:
         #videothumbnail = commands.getoutput(grabimage)
         print "---------------IMAGE---------------"
         print "VIDEOTHUMBNAIL: %s" % videothumbnail
    except Exception as e:
         videothumbnail = None
         print("Failed to convert video file %s to %s" % (sourcefile, thumbnailfilename))
         print(traceback.format_exc())
    video.videothumbnail = imagefilename
    video.save()

#views.py
def upload_broadcast(request):
    if request.method == 'POST':
        form = BroadcastUploadForm(request.POST, request.FILES)
        if form.is_valid():
            upload=form.save()
            video_id = upload.id
            image_grab = ffmpeg_image.delay(video_id)
            video_conversion = convert_flv.delay(video_id)
            return HttpResponseRedirect('/current_classes/')
    else:
        form = BroadcastUploadForm(initial={'teacher': request.user,})
    return render_to_response('videos/create_video.html', {'form': form,}, context_instance=RequestContext(request))

#settings.py
DEFAULT_FILE_STORAGE = 'myapp.s3utils.MediaRootS3BotoStorage'
DEFAULT_S3_PATH = "media"
STATICFILES_STORAGE = 'myapp.s3utils.StaticRootS3BotoStorage'
STATIC_S3_PATH = "static"
AWS_STORAGE_BUCKET_NAME = 'my_bucket'
CLOUDFRONT_DOMAIN = 'domain.cloudfront.net'
AWS_ACCESS_KEY_ID = 'MY_KEY_ID'
AWS_SECRET_ACCESS_KEY = 'MY_SECRET_KEY'
MEDIA_ROOT = '/%s/' % DEFAULT_S3_PATH
MEDIA_URL = 'http://%s/%s/' % (CLOUDFRONT_DOMAIN, DEFAULT_S3_PATH)
...

#s3utils.py
from storages.backends.s3boto import S3BotoStorage
from django.utils.functional import SimpleLazyObject

StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage  = lambda: S3BotoStorage(location='media')

如果需要帮助我解决问题,我可以添加任何其他信息。在


Tags: tonameidtrues3modelsvideofilename
3条回答

嘿,你在犯一个简单的错误

而不是使用settings.Media\u url使用媒体根目录

不确定是否能从类似的云场景中获得帮助,包括上传到云的媒体文件(parse.com公司)这需要ffmpeg进程在到达时将输出(.mp4)写回云(通过Curl解析)。在

请参阅paste shellscript,该进程当前正在Heroku WEB进程中运行,该进程可以使用CLI调用脚本。在

如果您可以调整它,使shell脚本在某个进程中运行,该进程可以对输入进行http访问,并有一个文件系统,在该文件系统中可以编写临时文件,如果您可以CURL-X发布ffmpeg.output.输出从tmpfs返回到S3,那么它可能对u

为了使用subprocess.call使用包含所有参数的字符串 需要添加shell=True

ffmpegresult = subprocess.call(ffmpeg, shell=True)
...
videothumbnail = subprocess.call(grabimage, shell=True)

相关问题 更多 >