Reputation: 327
I have this code to transcode video and it works well without celery. With celery, the path of the file in the database shows a different path and the video cannot be played in the browser, but it saves the file in the correct location in the pc.
If I don't use celery, then the file path in database is media/videos/videos/<filename>.mp4
and file also gets saved here. This way the template is able to play the video. But if I use celery, the output gets saved in media/videos/videos/<filename>.mp4
but the path in database will be media/<filename>.mp4
somehow and thus template can't play the video.
Is it because my page gets updated before the task? and not getting saved properly?
views.py
def post(self, *args, **kwargs):
form = VideoPostForm(self.request.POST or None, self.request.FILES or None)
if form.is_valid():
video = form.save(commit=False)
video.user = self.request.user
video.save()
form.save_m2m()
# task_video_encoding(video.id)
task_video_encoding.delay(video.id)
return redirect('videos:my_video_home')
else:
raise ValidationError('Check all form fields.')
encoding.py
def encode_video(video_id):
video = VideoPost.objects.get(id = video_id)
input_file_path = video.temp_file.path
# print(input_file_path)
input_file_name = video.title
#get the filename (without extension)
filename = os.path.basename(input_file_path)
# print(filename)
# path to the new file, change it according to where you want to put it
output_file_name = os.path.join('{}.mp4'.format(filename))
# print(output_file_name)
# output_file_path = os.path.join(settings.MEDIA_ROOT, output_file_name)
output_file_path = os.path.join(settings.MEDIA_ROOT, 'videos', 'videos', output_file_name)
# print(output_file_path)
for i in range(1):
subprocess.call([settings.VIDEO_ENCODING_FFMPEG_PATH, '-i', input_file_path, '-codec:v', 'libx264', '-crf', '-preset',
'-b:v', '3000k', '-maxrate', '-bufsize', '6000k', '-vf', 'scale=-2:720',
'-codec:a', 'aac', '128k', '-strict', '-2', output_file_path])
# Save the new file in the database
video.file = output_file_name
video.save(update_fields=['file'])
print(video.file)
video.temp_file.delete()
models
class VideoPost(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
title = models.TextField(max_length=1000)
temp_file = models.FileField(upload_to='videos/temp_videos/', validators=[validate_file_extension], null=True)
file = models.FileField(upload_to='videos/videos/', validators=[validate_file_extension], blank=True, max_length=255)
post_date = models.DateTimeField(auto_now_add=True, verbose_name="Date Posted")
updated = models.DateTimeField(auto_now_add=True, verbose_name="Date Updated")
slug = models.SlugField(blank=True, unique=True, max_length=255)
Can anyone help me how to change this code in a way to show the converted video properly in the template.
Upvotes: 3
Views: 320
Reputation: 293
You can debug by using print(video.file)
to see if the output is <filename>.mp4
or videos/videos/<filename>.mp4
. I am skeptical that it will only printout the file name and not the url path, which is what you need.
Some suggestions:
In your template
:
Change {{ video.file }}
to {{ video.file.url }}
. See what it prints out.
Your current output_file_path = os.path.join(settings.MEDIA_ROOT, output_file_name)
will be something like media/<filename>.mp4
. The one you commented out will give output media/videos/videos/<filename>.mp4
. I am not sure what your subprocess
function would do with output_file_path
, but you can see if it has any problems in there.
Upvotes: 1