kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			Can now stream transcoded version of audio tracks \o/
							rodzic
							
								
									ddea5f1825
								
							
						
					
					
						commit
						1cfdf31e00
					
				| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
from django import forms
 | 
			
		||||
 | 
			
		||||
from . import models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TranscodeForm(forms.Form):
 | 
			
		||||
    FORMAT_CHOICES = [
 | 
			
		||||
        ('ogg', 'ogg'),
 | 
			
		||||
        ('mp3', 'mp3'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    to = forms.ChoiceField(choices=FORMAT_CHOICES)
 | 
			
		||||
    BITRATE_CHOICES = [
 | 
			
		||||
        (64, '64'),
 | 
			
		||||
        (128, '128'),
 | 
			
		||||
        (256, '256'),
 | 
			
		||||
    ]
 | 
			
		||||
    bitrate = forms.ChoiceField(
 | 
			
		||||
        choices=BITRATE_CHOICES, required=False)
 | 
			
		||||
 | 
			
		||||
    track_file = forms.ModelChoiceField(
 | 
			
		||||
        queryset=models.TrackFile.objects.all()
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,16 @@
 | 
			
		|||
import ffmpeg
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import subprocess
 | 
			
		||||
import unicodedata
 | 
			
		||||
import urllib
 | 
			
		||||
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.db import models, transaction
 | 
			
		||||
from django.db.models.functions import Length
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.http import StreamingHttpResponse
 | 
			
		||||
 | 
			
		||||
from rest_framework import viewsets, views, mixins
 | 
			
		||||
from rest_framework.decorators import detail_route, list_route
 | 
			
		||||
from rest_framework.response import Response
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +24,7 @@ from funkwhale_api.common.permissions import (
 | 
			
		|||
    ConditionalAuthentication, HasModelPermission)
 | 
			
		||||
from taggit.models import Tag
 | 
			
		||||
 | 
			
		||||
from . import forms
 | 
			
		||||
from . import models
 | 
			
		||||
from . import serializers
 | 
			
		||||
from . import importers
 | 
			
		||||
| 
						 | 
				
			
			@ -183,6 +189,40 @@ class TrackFileViewSet(viewsets.ReadOnlyModelViewSet):
 | 
			
		|||
            f.audio_file.url)
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
    @list_route(methods=['get'])
 | 
			
		||||
    def viewable(self, request, *args, **kwargs):
 | 
			
		||||
        return Response({}, status=200)
 | 
			
		||||
 | 
			
		||||
    @list_route(methods=['get'])
 | 
			
		||||
    def transcode(self, request, *args, **kwargs):
 | 
			
		||||
        form = forms.TranscodeForm(request.GET)
 | 
			
		||||
        if not form.is_valid():
 | 
			
		||||
            return Response(form.errors, status=400)
 | 
			
		||||
 | 
			
		||||
        f = form.cleaned_data['track_file']
 | 
			
		||||
        output_kwargs = {
 | 
			
		||||
            'format': form.cleaned_data['to']
 | 
			
		||||
        }
 | 
			
		||||
        args = (ffmpeg
 | 
			
		||||
            .input(f.audio_file.path)
 | 
			
		||||
            .output('pipe:', **output_kwargs)
 | 
			
		||||
            .get_args()
 | 
			
		||||
        )
 | 
			
		||||
        # we use a generator here so the view return immediatly and send
 | 
			
		||||
        # file chunk to the browser, instead of blocking a few seconds
 | 
			
		||||
        def _transcode():
 | 
			
		||||
            p = subprocess.Popen(
 | 
			
		||||
                ['ffmpeg'] + args,
 | 
			
		||||
                stdout=subprocess.PIPE)
 | 
			
		||||
            for line in p.stdout:
 | 
			
		||||
                yield line
 | 
			
		||||
 | 
			
		||||
        response = StreamingHttpResponse(
 | 
			
		||||
            _transcode(), status=200,
 | 
			
		||||
            content_type=form.cleaned_data['to'])
 | 
			
		||||
 | 
			
		||||
        return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TagViewSet(viewsets.ReadOnlyModelViewSet):
 | 
			
		||||
    queryset = Tag.objects.all().order_by('name')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue