diff --git a/.env.dev b/.env.dev
index 7e9eb3bf153bfa741d1ad369b38c24124ef1cd38..e117dbe562c0fc536686a896994b62f96111d7d5 100644
--- a/.env.dev
+++ b/.env.dev
@@ -10,3 +10,4 @@ PYTHONDONTWRITEBYTECODE=true
 WEBPACK_DEVSERVER_PORT=8080
 MUSIC_DIRECTORY_PATH=/music
 BROWSABLE_API_ENABLED=True
+CACHEOPS_ENABLED=False
diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py
index 0754c4b2f44123e743f9df503c4457b529a17584..891609cbaa30117bbe0eccf802405a89c56b4914 100644
--- a/api/funkwhale_api/federation/factories.py
+++ b/api/funkwhale_api/federation/factories.py
@@ -233,6 +233,9 @@ class AudioMetadataFactory(factory.Factory):
     release = factory.LazyAttribute(
         lambda o: 'https://musicbrainz.org/release/{}'.format(uuid.uuid4())
     )
+    bitrate = 42
+    length = 43
+    size = 44
 
     class Meta:
         model = dict
diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py
index d91a00c8b50f5c103fc818f9dea47f6a55cbf9cf..69d0ea9254e7f28c7d54eb683b986a7b9d7b2033 100644
--- a/api/funkwhale_api/federation/models.py
+++ b/api/funkwhale_api/federation/models.py
@@ -216,3 +216,6 @@ class LibraryTrack(models.Model):
             for chunk in r.iter_content(chunk_size=512):
                 tmp_file.write(chunk)
             self.audio_file.save(filename, tmp_file)
+
+    def get_metadata(self, key):
+        return self.metadata.get(key)
diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 426aabd771b1e5caaaa683648a123ccbe00aa986..8d3dd6379b2f327cfb9b11821b02d34527518171 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -688,6 +688,12 @@ class AudioMetadataSerializer(serializers.Serializer):
     artist = ArtistMetadataSerializer()
     release = ReleaseMetadataSerializer()
     recording = RecordingMetadataSerializer()
+    bitrate = serializers.IntegerField(
+        required=False, allow_null=True, min_value=0)
+    size = serializers.IntegerField(
+        required=False, allow_null=True, min_value=0)
+    length = serializers.IntegerField(
+        required=False, allow_null=True, min_value=0)
 
 
 class AudioSerializer(serializers.Serializer):
@@ -760,6 +766,9 @@ class AudioSerializer(serializers.Serializer):
                     'musicbrainz_id': str(track.mbid) if track.mbid else None,
                     'title': track.title,
                 },
+                'bitrate': instance.bitrate,
+                'size': instance.size,
+                'length': instance.duration,
             },
             'url': {
                 'href': utils.full_url(instance.path),
diff --git a/api/funkwhale_api/music/admin.py b/api/funkwhale_api/music/admin.py
index 667a7c2a1b10659c4d608fa2af5b6bcaf04e2681..1654428baf866df98f9888c6b101cce2425702cd 100644
--- a/api/funkwhale_api/music/admin.py
+++ b/api/funkwhale_api/music/admin.py
@@ -74,6 +74,8 @@ class TrackFileAdmin(admin.ModelAdmin):
         'source',
         'duration',
         'mimetype',
+        'size',
+        'bitrate'
     ]
     list_select_related = [
         'track'
diff --git a/api/funkwhale_api/music/factories.py b/api/funkwhale_api/music/factories.py
index 1df949904db992e2cd295d02e4acbfed9d212627..412e2f798835579217f6fa84b35e926d59baaba9 100644
--- a/api/funkwhale_api/music/factories.py
+++ b/api/funkwhale_api/music/factories.py
@@ -54,6 +54,10 @@ class TrackFileFactory(factory.django.DjangoModelFactory):
     audio_file = factory.django.FileField(
         from_path=os.path.join(SAMPLES_PATH, 'test.ogg'))
 
+    bitrate = None
+    size = None
+    duration = None
+
     class Meta:
         model = 'music.TrackFile'
 
diff --git a/api/funkwhale_api/music/management/commands/fix_track_files.py b/api/funkwhale_api/music/management/commands/fix_track_files.py
index f68bcf1359d4661710a98ee443ff1578824f46f2..9adc1b9bf1a9d24f3cb26b6da4dce68dc6078213 100644
--- a/api/funkwhale_api/music/management/commands/fix_track_files.py
+++ b/api/funkwhale_api/music/management/commands/fix_track_files.py
@@ -2,6 +2,7 @@ import cacheops
 import os
 
 from django.db import transaction
+from django.db.models import Q
 from django.conf import settings
 from django.core.management.base import BaseCommand, CommandError
 
@@ -24,6 +25,8 @@ class Command(BaseCommand):
         if options['dry_run']:
             self.stdout.write('Dry-run on, will not commit anything')
         self.fix_mimetypes(**options)
+        self.fix_file_data(**options)
+        self.fix_file_size(**options)
         cacheops.invalidate_model(models.TrackFile)
 
     @transaction.atomic
@@ -43,3 +46,60 @@ class Command(BaseCommand):
             if not dry_run:
                 self.stdout.write('[mimetypes] commiting...')
                 qs.update(mimetype=mimetype)
+
+    def fix_file_data(self, dry_run, **kwargs):
+        self.stdout.write('Fixing missing bitrate or length...')
+        matching = models.TrackFile.objects.filter(
+            Q(bitrate__isnull=True) | Q(duration__isnull=True))
+        total = matching.count()
+        self.stdout.write(
+            '[bitrate/length] {} entries found with missing values'.format(
+                total))
+        if dry_run:
+            return
+        for i, tf in enumerate(matching.only('audio_file')):
+            self.stdout.write(
+                '[bitrate/length] {}/{} fixing file #{}'.format(
+                    i+1, total, tf.pk
+                ))
+
+            try:
+                audio_file = tf.get_audio_file()
+                if audio_file:
+                    with audio_file as f:
+                        data = utils.get_audio_file_data(audio_file)
+                    tf.bitrate = data['bitrate']
+                    tf.duration = data['length']
+                    tf.save(update_fields=['duration', 'bitrate'])
+                else:
+                    self.stderr.write('[bitrate/length] no file found')
+            except Exception as e:
+                self.stderr.write(
+                    '[bitrate/length] error with file #{}: {}'.format(
+                        tf.pk, str(e)
+                    )
+                )
+
+    def fix_file_size(self, dry_run, **kwargs):
+        self.stdout.write('Fixing missing size...')
+        matching = models.TrackFile.objects.filter(size__isnull=True)
+        total = matching.count()
+        self.stdout.write(
+            '[size] {} entries found with missing values'.format(total))
+        if dry_run:
+            return
+        for i, tf in enumerate(matching.only('size')):
+            self.stdout.write(
+                '[size] {}/{} fixing file #{}'.format(
+                    i+1, total, tf.pk
+                ))
+
+            try:
+                tf.size = tf.get_file_size()
+                tf.save(update_fields=['size'])
+            except Exception as e:
+                self.stderr.write(
+                    '[size] error with file #{}: {}'.format(
+                        tf.pk, str(e)
+                    )
+                )
diff --git a/api/funkwhale_api/music/migrations/0027_auto_20180515_1808.py b/api/funkwhale_api/music/migrations/0027_auto_20180515_1808.py
new file mode 100644
index 0000000000000000000000000000000000000000..835e115a6571c010148c939f11f15023a1d42475
--- /dev/null
+++ b/api/funkwhale_api/music/migrations/0027_auto_20180515_1808.py
@@ -0,0 +1,29 @@
+# Generated by Django 2.0.3 on 2018-05-15 18:08
+
+from django.db import migrations, models
+import taggit.managers
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('music', '0026_trackfile_accessed_date'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='trackfile',
+            name='bitrate',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='trackfile',
+            name='size',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='track',
+            name='tags',
+            field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
+        ),
+    ]
diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py
index 294bce354de0eb6dd6b50d71c1eff6234afe132a..1259cc3c12406a7848649d829dfed7e8999f4539 100644
--- a/api/funkwhale_api/music/models.py
+++ b/api/funkwhale_api/music/models.py
@@ -429,6 +429,8 @@ class TrackFile(models.Model):
     modification_date = models.DateTimeField(auto_now=True)
     accessed_date = models.DateTimeField(null=True, blank=True)
     duration = models.IntegerField(null=True, blank=True)
+    size = models.IntegerField(null=True, blank=True)
+    bitrate = models.IntegerField(null=True, blank=True)
     acoustid_track_id = models.UUIDField(null=True, blank=True)
     mimetype = models.CharField(null=True, blank=True, max_length=200)
 
@@ -477,6 +479,41 @@ class TrackFile(models.Model):
             return
         return os.path.splitext(self.audio_file.name)[-1].replace('.', '', 1)
 
+    def get_file_size(self):
+        if self.audio_file:
+            return self.audio_file.size
+
+        if self.source.startswith('file://'):
+            return os.path.getsize(self.source.replace('file://', '', 1))
+
+        if self.library_track and self.library_track.audio_file:
+            return self.library_track.audio_file.size
+
+    def get_audio_file(self):
+        if self.audio_file:
+            return self.audio_file.open()
+        if self.source.startswith('file://'):
+            return open(self.source.replace('file://', '', 1), 'rb')
+        if self.library_track and self.library_track.audio_file:
+            return self.library_track.audio_file.open()
+
+    def set_audio_data(self):
+        audio_file = self.get_audio_file()
+        if audio_file:
+            with audio_file as f:
+                audio_data = utils.get_audio_file_data(f)
+            if not audio_data:
+                return
+            self.duration = int(audio_data['length'])
+            self.bitrate = audio_data['bitrate']
+            self.size = self.get_file_size()
+        else:
+            lt = self.library_track
+            if lt:
+                self.duration = lt.get_metadata('length')
+                self.size = lt.get_metadata('size')
+                self.bitrate = lt.get_metadata('bitrate')
+
     def save(self, **kwargs):
         if not self.mimetype and self.audio_file:
             self.mimetype = utils.guess_mimetype(self.audio_file)
diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py
index 9dfc9147872871b0f0ba500c213f812b79bad8d7..d9d48496e487395be4ff0516b64f43b1074f37c1 100644
--- a/api/funkwhale_api/music/serializers.py
+++ b/api/funkwhale_api/music/serializers.py
@@ -27,6 +27,7 @@ class SimpleArtistSerializer(serializers.ModelSerializer):
 
 class ArtistSerializer(serializers.ModelSerializer):
     tags = TagSerializer(many=True, read_only=True)
+
     class Meta:
         model = models.Artist
         fields = ('id', 'mbid', 'name', 'tags', 'creation_date')
@@ -40,11 +41,21 @@ class TrackFileSerializer(serializers.ModelSerializer):
         fields = (
             'id',
             'path',
-            'duration',
             'source',
             'filename',
             'mimetype',
-            'track')
+            'track',
+            'duration',
+            'mimetype',
+            'bitrate',
+            'size',
+        )
+        read_only_fields = [
+            'duration',
+            'mimetype',
+            'bitrate',
+            'size',
+        ]
 
     def get_path(self, o):
         url = o.path
diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py
index bad0006aa98520e2afac00aad8d5466bde2b8934..34345e47b49e9f44f41bb341ebdb059ff5185464 100644
--- a/api/funkwhale_api/music/tasks.py
+++ b/api/funkwhale_api/music/tasks.py
@@ -134,6 +134,7 @@ def _do_import(import_job, replace=False, use_acoustid=True):
         # in place import, we set mimetype from extension
         path, ext = os.path.splitext(import_job.source)
         track_file.mimetype = music_utils.get_type_from_ext(ext)
+    track_file.set_audio_data()
     track_file.save()
     import_job.status = 'finished'
     import_job.track_file = track_file
diff --git a/api/funkwhale_api/music/utils.py b/api/funkwhale_api/music/utils.py
index 329a99bed9b0577efc3f9c3b4260c70eb724f5f3..f11e4507a7a0bc7d1648e5dfda18f3deb4542286 100644
--- a/api/funkwhale_api/music/utils.py
+++ b/api/funkwhale_api/music/utils.py
@@ -1,5 +1,6 @@
 import magic
 import mimetypes
+import mutagen
 import re
 
 from django.db.models import Q
@@ -66,7 +67,7 @@ def compute_status(jobs):
 AUDIO_EXTENSIONS_AND_MIMETYPE = [
     ('ogg', 'audio/ogg'),
     ('mp3', 'audio/mpeg'),
-    ('flac', 'audio/flac'),
+    ('flac', 'audio/x-flac'),
 ]
 
 EXTENSION_TO_MIMETYPE = {ext: mt for ext, mt in AUDIO_EXTENSIONS_AND_MIMETYPE}
@@ -82,3 +83,14 @@ def get_type_from_ext(extension):
         # we remove leading dot
         extension = extension[1:]
     return EXTENSION_TO_MIMETYPE.get(extension)
+
+
+def get_audio_file_data(f):
+    data = mutagen.File(f)
+    if not data:
+        return
+    d = {}
+    d['bitrate'] = data.info.bitrate
+    d['length'] = data.info.length
+
+    return d
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index f06f86f1d036f9c5cd0839957ff96b58f41bfb81..f2ab72c5a020f4745a932dbbb50c3233030c9497 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -268,6 +268,10 @@ def handle_serve(track_file):
                 qs = LibraryTrack.objects.select_for_update()
                 library_track = qs.get(pk=library_track.pk)
                 library_track.download_audio()
+            track_file.library_track = library_track
+            track_file.set_audio_data()
+            track_file.save(update_fields=['bitrate', 'duration', 'size'])
+
         audio_file = library_track.audio_file
         file_path = get_file_path(audio_file)
         mt = library_track.audio_mimetype
@@ -296,7 +300,11 @@ def handle_serve(track_file):
 
 
 class TrackFileViewSet(viewsets.ReadOnlyModelViewSet):
-    queryset = (models.TrackFile.objects.all().order_by('-id'))
+    queryset = (
+        models.TrackFile.objects.all()
+            .select_related('track__artist', 'track__album')
+            .order_by('-id')
+    )
     serializer_class = serializers.TrackFileSerializer
     authentication_classes = rest_settings.api_settings.DEFAULT_AUTHENTICATION_CLASSES + [
         SignatureAuthentication
diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py
index 5bc452886d7486bdc0ad7c1f5571ea69fc405895..6709930f56756abae175f1158bae0f9d94ec67b7 100644
--- a/api/funkwhale_api/subsonic/serializers.py
+++ b/api/funkwhale_api/subsonic/serializers.py
@@ -81,6 +81,10 @@ def get_track_data(album, track, tf):
         'artistId': album.artist.pk,
         'type': 'music',
     }
+    if tf.bitrate:
+        data['bitrate'] = int(tf.bitrate/1000)
+    if tf.size:
+        data['size'] = tf.size
     if album.release_date:
         data['year'] = album.release_date.year
     return data
@@ -211,5 +215,9 @@ def get_music_directory_data(artist):
             'parent': artist.id,
             'type': 'music',
         }
+        if tf.bitrate:
+            td['bitrate'] = int(tf.bitrate/1000)
+        if tf.size:
+            td['size'] = tf.size
         data['child'].append(td)
     return data
diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py
index 85208fa490b53dd52b998b24f6f743f9d465d785..f298c61f5fbd36f9516e607d00e60649c4b9b281 100644
--- a/api/tests/federation/test_serializers.py
+++ b/api/tests/federation/test_serializers.py
@@ -533,7 +533,12 @@ def test_activity_pub_audio_serializer_to_library_track_no_duplicate(
 
 
 def test_activity_pub_audio_serializer_to_ap(factories):
-    tf = factories['music.TrackFile'](mimetype='audio/mp3')
+    tf = factories['music.TrackFile'](
+        mimetype='audio/mp3',
+        bitrate=42,
+        duration=43,
+        size=44,
+    )
     library = actors.SYSTEM_ACTORS['library'].get_actor_instance()
     expected = {
         '@context': serializers.AP_CONTEXT,
@@ -555,6 +560,9 @@ def test_activity_pub_audio_serializer_to_ap(factories):
                 'musicbrainz_id': tf.track.mbid,
                 'title': tf.track.title,
             },
+            'size': tf.size,
+            'length': tf.duration,
+            'bitrate': tf.bitrate,
         },
         'url': {
             'href': utils.full_url(tf.path),
@@ -599,6 +607,9 @@ def test_activity_pub_audio_serializer_to_ap_no_mbid(factories):
                 'title': tf.track.title,
                 'musicbrainz_id': None,
             },
+            'size': None,
+            'length': None,
+            'bitrate': None,
         },
         'url': {
             'href': utils.full_url(tf.path),
diff --git a/api/tests/music/test_commands.py b/api/tests/music/test_commands.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff3343aa53fd13be34c99316c2da38c188571e93
--- /dev/null
+++ b/api/tests/music/test_commands.py
@@ -0,0 +1,45 @@
+from funkwhale_api.music.management.commands import fix_track_files
+
+
+def test_fix_track_files_bitrate_length(factories, mocker):
+    tf1 = factories['music.TrackFile'](bitrate=1, duration=2)
+    tf2 = factories['music.TrackFile'](bitrate=None, duration=None)
+    c = fix_track_files.Command()
+
+    mocker.patch(
+        'funkwhale_api.music.utils.get_audio_file_data',
+        return_value={'bitrate': 42, 'length': 43})
+
+    c.fix_file_data(dry_run=False)
+
+    tf1.refresh_from_db()
+    tf2.refresh_from_db()
+
+    # not updated
+    assert tf1.bitrate == 1
+    assert tf1.duration == 2
+
+    # updated
+    assert tf2.bitrate == 42
+    assert tf2.duration == 43
+
+
+def test_fix_track_files_size(factories, mocker):
+    tf1 = factories['music.TrackFile'](size=1)
+    tf2 = factories['music.TrackFile'](size=None)
+    c = fix_track_files.Command()
+
+    mocker.patch(
+        'funkwhale_api.music.models.TrackFile.get_file_size',
+        return_value=2)
+
+    c.fix_file_size(dry_run=False)
+
+    tf1.refresh_from_db()
+    tf2.refresh_from_db()
+
+    # not updated
+    assert tf1.size == 1
+
+    # updated
+    assert tf2.size == 2
diff --git a/api/tests/music/test_import.py b/api/tests/music/test_import.py
index c7b40fb16e9ebc50e33060b88c0c82947e808451..8453dca8407ad551f70930a00d5e16494560ab38 100644
--- a/api/tests/music/test_import.py
+++ b/api/tests/music/test_import.py
@@ -1,4 +1,5 @@
 import json
+import os
 import pytest
 
 from django.urls import reverse
@@ -7,6 +8,8 @@ from funkwhale_api.federation import actors
 from funkwhale_api.federation import serializers as federation_serializers
 from funkwhale_api.music import tasks
 
+DATA_DIR = os.path.dirname(os.path.abspath(__file__))
+
 
 def test_create_import_can_bind_to_request(
         artists, albums, mocker, factories, superuser_api_client):
@@ -40,11 +43,20 @@ def test_create_import_can_bind_to_request(
     assert batch.import_request == request
 
 
-def test_import_job_from_federation_no_musicbrainz(factories):
+def test_import_job_from_federation_no_musicbrainz(factories, mocker):
+    mocker.patch(
+        'funkwhale_api.music.utils.get_audio_file_data',
+        return_value={'bitrate': 24, 'length': 666})
+    mocker.patch(
+        'funkwhale_api.music.models.TrackFile.get_file_size',
+        return_value=42)
     lt = factories['federation.LibraryTrack'](
         artist_name='Hello',
         album_title='World',
         title='Ping',
+        metadata__length=42,
+        metadata__bitrate=43,
+        metadata__size=44,
     )
     job = factories['music.ImportJob'](
         federation=True,
@@ -56,6 +68,9 @@ def test_import_job_from_federation_no_musicbrainz(factories):
 
     tf = job.track_file
     assert tf.mimetype == lt.audio_mimetype
+    assert tf.duration == 42
+    assert tf.bitrate == 43
+    assert tf.size == 44
     assert tf.library_track == job.library_track
     assert tf.track.title == 'Ping'
     assert tf.track.artist.name == 'Hello'
@@ -234,13 +249,13 @@ def test_import_batch_notifies_followers(
 
 
 def test__do_import_in_place_mbid(factories, tmpfile):
-    path = '/test.ogg'
+    path = os.path.join(DATA_DIR, 'test.ogg')
     job = factories['music.ImportJob'](
-        in_place=True, source='file:///test.ogg')
+        in_place=True, source='file://{}'.format(path))
 
     track = factories['music.Track'](mbid=job.mbid)
     tf = tasks._do_import(job, use_acoustid=False)
 
     assert bool(tf.audio_file) is False
-    assert tf.source == 'file:///test.ogg'
+    assert tf.source == 'file://{}'.format(path)
     assert tf.mimetype == 'audio/ogg'
diff --git a/api/tests/music/test_models.py b/api/tests/music/test_models.py
index d76c09a01e41a4e63416e5b4da7a1f07a24d9515..e926d07fa2be7c367b50e53acbc72666eca8b06b 100644
--- a/api/tests/music/test_models.py
+++ b/api/tests/music/test_models.py
@@ -85,3 +85,28 @@ def test_track_file_file_name(factories):
     tf = factories['music.TrackFile'](audio_file__from_path=path)
 
     assert tf.filename == tf.track.full_name + '.mp3'
+
+
+def test_track_get_file_size(factories):
+    name = 'test.mp3'
+    path = os.path.join(DATA_DIR, name)
+    tf = factories['music.TrackFile'](audio_file__from_path=path)
+
+    assert tf.get_file_size() == 297745
+
+
+def test_track_get_file_size_federation(factories):
+    tf = factories['music.TrackFile'](
+        federation=True,
+        library_track__with_audio_file=True)
+
+    assert tf.get_file_size() == tf.library_track.audio_file.size
+
+
+def test_track_get_file_size_in_place(factories):
+    name = 'test.mp3'
+    path = os.path.join(DATA_DIR, name)
+    tf = factories['music.TrackFile'](
+        in_place=True, source='file://{}'.format(path))
+
+    assert tf.get_file_size() == 297745
diff --git a/api/tests/music/test_tasks.py b/api/tests/music/test_tasks.py
index ddbc4ba9a2c7407bd067dc2799f499654cbb004c..c5839432bf128a3a03387bb2894d8ad56615594b 100644
--- a/api/tests/music/test_tasks.py
+++ b/api/tests/music/test_tasks.py
@@ -62,6 +62,9 @@ def test_import_job_can_run_with_file_and_acoustid(
             'score': 0.860825}],
         'status': 'ok'
     }
+    mocker.patch(
+        'funkwhale_api.music.utils.get_audio_file_data',
+        return_value={'bitrate': 42, 'length': 43})
     mocker.patch(
         'funkwhale_api.musicbrainz.api.artists.get',
         return_value=artists['get']['adhesive_wombat'])
@@ -82,7 +85,9 @@ def test_import_job_can_run_with_file_and_acoustid(
 
     with open(path, 'rb') as f:
         assert track_file.audio_file.read() == f.read()
-    assert track_file.duration == 268
+    assert track_file.bitrate == 42
+    assert track_file.duration == 43
+    assert track_file.size == os.path.getsize(path)
     # audio file is deleted from import job once persisted to audio file
     assert not job.audio_file
     assert job.status == 'finished'
diff --git a/api/tests/music/test_utils.py b/api/tests/music/test_utils.py
index 0a4f4b99424c34557fb846866b6e1b2958244a88..12b381a997c59ea85ebf1239024b1d3f288e2cdf 100644
--- a/api/tests/music/test_utils.py
+++ b/api/tests/music/test_utils.py
@@ -1,5 +1,10 @@
+import os
+import pytest
+
 from funkwhale_api.music import utils
 
+DATA_DIR = os.path.dirname(os.path.abspath(__file__))
+
 
 def test_guess_mimetype_try_using_extension(factories, mocker):
     mocker.patch(
@@ -17,3 +22,16 @@ def test_guess_mimetype_try_using_extension_if_fail(factories, mocker):
         audio_file__filename='test.mp3')
 
     assert utils.guess_mimetype(f.audio_file) == 'audio/mpeg'
+
+
+@pytest.mark.parametrize('name, expected', [
+    ('sample.flac', {'bitrate': 1608000, 'length': 0.001}),
+    ('test.mp3', {'bitrate': 8000, 'length': 267.70285714285717}),
+    ('test.ogg', {'bitrate': 128000, 'length': 229.18304166666667}),
+])
+def test_get_audio_file_data(name, expected):
+    path = os.path.join(DATA_DIR, name)
+    with open(path, 'rb') as f:
+        result = utils.get_audio_file_data(f)
+
+    assert result == expected
diff --git a/api/tests/subsonic/test_serializers.py b/api/tests/subsonic/test_serializers.py
index 6da9dd12e2e273643cf78ec0410535e77891fdad..ad9f739a1dd63ae2036142b2bdab149dc9e63635 100644
--- a/api/tests/subsonic/test_serializers.py
+++ b/api/tests/subsonic/test_serializers.py
@@ -77,7 +77,8 @@ def test_get_album_serializer(factories):
     artist = factories['music.Artist']()
     album = factories['music.Album'](artist=artist)
     track = factories['music.Track'](album=album)
-    tf = factories['music.TrackFile'](track=track)
+    tf = factories['music.TrackFile'](
+        track=track, bitrate=42000, duration=43, size=44)
 
     expected = {
         'id': album.pk,
@@ -98,7 +99,9 @@ def test_get_album_serializer(factories):
                 'year': track.album.release_date.year,
                 'contentType': tf.mimetype,
                 'suffix': tf.extension or '',
-                'duration': tf.duration or 0,
+                'bitrate': 42,
+                'duration': 43,
+                'size': 44,
                 'created': track.creation_date,
                 'albumId': album.pk,
                 'artistId': artist.pk,
@@ -177,7 +180,8 @@ def test_playlist_detail_serializer(factories):
 
 def test_directory_serializer_artist(factories):
     track = factories['music.Track']()
-    tf = factories['music.TrackFile'](track=track)
+    tf = factories['music.TrackFile'](
+        track=track, bitrate=42000, duration=43, size=44)
     album = track.album
     artist = track.artist
 
@@ -195,7 +199,9 @@ def test_directory_serializer_artist(factories):
             'year': track.album.release_date.year,
             'contentType': tf.mimetype,
             'suffix': tf.extension or '',
-            'duration': tf.duration or 0,
+            'bitrate': 42,
+            'duration': 43,
+            'size': 44,
             'created': track.creation_date,
             'albumId': album.pk,
             'artistId': artist.pk,
diff --git a/changes/changelog.d/195.feature b/changes/changelog.d/195.feature
new file mode 100644
index 0000000000000000000000000000000000000000..62411d8ef2445b5adcd3c7b9e5de9257728467c4
--- /dev/null
+++ b/changes/changelog.d/195.feature
@@ -0,0 +1,42 @@
+Store file length, size and bitrate (#195)
+
+
+Storage of bitrate, size and length in database
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Starting with this release, when importing files, Funkwhale will store
+additional information about audio files:
+
+- Bitrate
+- Size (in bytes)
+- Duration
+
+This change is not retroactive, meaning already imported files will lack those
+informations. The interface and API should work as before in such case, however,
+we offer a command to deal with legacy files and populate the missing values.
+
+On docker setups:
+
+.. code-block:: shell
+
+    docker-compose run --rm api python manage.py fix_track_files
+
+
+On non-docker setups:
+
+.. code-block:: shell
+
+    # from your activated virtualenv
+    python manage.py fix_track_files
+
+.. note::
+
+    The execution time for this command is proportional to the number of
+    audio files stored on your instance. This is because we need to read the
+    files from disk to fetch the data. You can run it in the background
+    while Funkwhale is up.
+
+    It's also safe to interrupt this command and rerun it at a later point, or run
+    it multiple times.
+
+    Use the --dry-run flag to check how many files would be impacted.
diff --git a/front/src/audio/formats.js b/front/src/audio/formats.js
index a4c2ecf0efcd3e5f46d68a928d57350b87197bed..d8a5a412546433ce73d5641c0aee075a480aba75 100644
--- a/front/src/audio/formats.js
+++ b/front/src/audio/formats.js
@@ -6,6 +6,6 @@ export default {
   formatsMap: {
     'audio/ogg': 'ogg',
     'audio/mpeg': 'mp3',
-    'audio/flac': 'flac'
+    'audio/x-flac': 'flac'
   }
 }
diff --git a/front/src/components/library/Track.vue b/front/src/components/library/Track.vue
index 940086e02aa9263bcab6924a75c161aacb5aa5dd..155a1245a58c413169059a5db988b88d2c8e7b6e 100644
--- a/front/src/components/library/Track.vue
+++ b/front/src/components/library/Track.vue
@@ -44,6 +44,46 @@
           </a>
         </div>
       </div>
+      <div v-if="file" class="ui vertical stripe center aligned segment">
+        <h2 class="ui header">{{ $t('Track information') }}</h2>
+        <table class="ui very basic collapsing celled center aligned table">
+          <tbody>
+            <tr>
+              <td>
+                {{ $t('Duration') }}
+              </td>
+              <td v-if="file.duration">
+                {{ time.parse(file.duration) }}
+              </td>
+              <td v-else>
+                {{ $t('N/A') }}
+              </td>
+            </tr>
+            <tr>
+              <td>
+                {{ $t('Size') }}
+              </td>
+              <td v-if="file.size">
+                {{ file.size | humanSize }}
+              </td>
+              <td v-else>
+                {{ $t('N/A') }}
+              </td>
+            </tr>
+            <tr>
+              <td>
+                {{ $t('Bitrate') }}
+              </td>
+              <td v-if="file.bitrate">
+                {{ file.bitrate | humanSize }}/s
+              </td>
+              <td v-else>
+                {{ $t('N/A') }}
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
       <div class="ui vertical stripe center aligned segment">
         <h2><i18next path="Lyrics"/></h2>
         <div v-if="isLoadingLyrics" class="ui vertical segment">
@@ -64,6 +104,8 @@
 </template>
 
 <script>
+
+import time from '@/utils/time'
 import axios from 'axios'
 import url from '@/utils/url'
 import logger from '@/logging'
@@ -83,6 +125,7 @@ export default {
   },
   data () {
     return {
+      time,
       isLoadingTrack: true,
       isLoadingLyrics: true,
       track: null,
@@ -134,6 +177,9 @@ export default {
         return u
       }
     },
+    file () {
+      return this.track.files[0]
+    },
     lyricsSearchUrl () {
       let base = 'http://lyrics.wikia.com/wiki/Special:Search?query='
       let query = this.track.artist.name + ' ' + this.track.title
@@ -159,5 +205,8 @@ export default {
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped lang="scss">
-
+.table.center.aligned {
+  margin-left: auto;
+  margin-right: auto;
+}
 </style>
diff --git a/front/src/filters.js b/front/src/filters.js
index afc393d402e8f80e046d2bd4443e3f03da2f07a7..11751559961c393b9d5bb3369aba199f8badf34a 100644
--- a/front/src/filters.js
+++ b/front/src/filters.js
@@ -47,4 +47,23 @@ export function capitalize (str) {
 
 Vue.filter('capitalize', capitalize)
 
+export function humanSize (bytes) {
+  let si = true
+  var thresh = si ? 1000 : 1024
+  if (Math.abs(bytes) < thresh) {
+    return bytes + ' B'
+  }
+  var units = si
+    ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+    : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
+  var u = -1
+  do {
+    bytes /= thresh
+    ++u
+  } while (Math.abs(bytes) >= thresh && u < units.length - 1)
+  return bytes.toFixed(1) + ' ' + units[u]
+}
+
+Vue.filter('humanSize', humanSize)
+
 export default {}