2012-06-17 5 views
3

Je travaille sur un algorithme qui nécessite un accès aléatoire très rapide aux images vidéo dans une vidéo éventuellement longue (minimum 30 minutes). J'utilise actuellement VideoCapture d'OpenCV pour lire ma vidéo, mais la fonctionnalité de recherche est cassée ou très lente. Le meilleur que j'ai trouvé jusqu'ici est d'utiliser le codec MJPEG dans un conteneur MKV, mais ce n'est pas assez rapide.Enregistrer une vidéo dans une base de données SQLite?

Je peux choisir n'importe quel format vidéo ou même en créer un nouveau. L'espace de stockage n'est pas un problème (à certains égards bien sûr). La seule exigence est d'obtenir le temps de recherche le plus rapide possible à n'importe quel endroit de la vidéo. Idéalement, j'aimerais pouvoir accéder simultanément à plusieurs images en profitant de mon processeur quad-core.

Je sais que les bases de données relationnelles sont très bien pour stocker de gros volumes de données, elles permettent des accès en lecture simultanés et elles sont très rapides lors de l'utilisation d'index.

SQLite convient-il à mes besoins spécifiques? Je prévois de stocker chaque image vidéo compressée en JPEG, et d'utiliser un index sur le numéro de la trame pour y accéder rapidement.

EDIT: pour moi un le cadre est juste une image, pas toute la vidéo. Une vidéo de 30mn @ 25 fps contient 30 * 60 * 25 = 45000 images, et je veux être en mesure d'en obtenir rapidement un en utilisant son numéro.

EDIT: Pour ceux qui pourraient être intéressés, j'ai finalement implémenté un conteneur vidéo personnalisé en sauvegardant chaque image dans des blocs de taille fixe (par conséquent, la position de n'importe quelle image peut être directement calculée!). Les images sont compressées avec la bibliothèque turbojpeg et les accès aux fichiers sont multi-threadés (pour être compatibles NCQ). Le goulot d'étranglement n'est plus le disque dur et j'ai finalement obtenu beaucoup mieux perfs :)

+0

@Cicada: il n'y a aucune limite sur la taille de la vidéo. Pour l'instant, je travaille sur une vidéo VGA 30mn (500 Mo en MPEG, 1,7 Go en MJPEG), mais le programme est censé fonctionner sur 5 heures de vidéo. Que voulez-vous dire par "système de fichiers"? J'ai besoin de traiter la requête comme "get frame 1530" aussi vite que possible. Utiliser une base de données est une suggestion, si vous avez une meilleure idée, je suis ouvert! –

+0

SQLite a une limite intégrée de 1 Go (953 Mio) par BLOB, donc chacune de vos images séparées ne peut pas être plus grande que cela. Ce que je veux dire, c'est pourquoi ne pas stocker des cadres directement sous forme de fichiers? Une base de données n'est pas adaptée à ce que vous essayez de faire. –

+0

@Cicada: Peut-être que j'ai utilisé la mauvaise formulation (je ne suis pas anglais natif). Pour moi, un cadre est juste une image, donc il ne sera pas plus grand que 1 Mo. Une vidéo de 30mn à 25 ips contient 30 * 60 * 25 = 45000 images. Une vidéo de 5h nécessiterait 450 000 fichiers, je ne pense pas que ce soit une bonne solution. –

Répondre

4

Je ne pense pas que l'utilisation de SQLite (ou de tout autre moteur dabatase) soit une bonne solution à votre problème. Une base de données est et non un système de fichiers.

Si ce que vous avez besoin est très rapide accès aléatoire, puis coller au système de fichiers, il a été conçu pour ce genre d'utilisation, et optimisé avec cela à l'esprit. Selon votre commentaire, vous dites qu'une vidéo de 5h nécessiterait 450k fichiers, eh bien, ce n'est pas un problème à mon avis. Certes, la liste des répertoires sera un peu longue, mais vous obtiendrez le absolu absolu accès aléatoire possible. Et il sera certainement plus rapide que SQLite parce que vous êtes un niveau d'abstraction sous.

Et si vous êtes vraiment inquiet au sujet des temps de liste de répertoires, il vous suffit d'organiser votre structure de dossiers comme un arbre. Cela vous obtiendra des chemins plus longs, mais une liste rapide.

+0

Sure liste de répertoire sera très lent, mais je m'en fous car je n'ai pas besoin de lister ces fichiers. La suggestion d'arborescence semble intéressante, mais l'utilisation de fichiers de 450 Ko rendra le «fichier vidéo» assez difficile à copier efficacement (dans mon expérience, il est toujours beaucoup plus rapide de copier un gros fichier que beaucoup de petits). Merci pour votre aide. –

+0

Encore une fois, les systèmes de fichiers modernes sont optimisés pour la copie de nombreux petits fichiers (en particulier EXT4), il vous suffit de choisir vos outils avec soin. –

+0

Malheureusement j'utilise NTFS, je ne connais pas ses performances avec de petits fichiers mais par expérience quand je copie des milliers de fichiers depuis et vers ma clé USB, c'est très lent. Beaucoup plus lent que lorsque je copie un film HD par exemple. Quoi qu'il en soit, je pense que je vais suivre votre conseil et stocker ma vidéo dans une structure arborescente: elle ne peut pas être plus lente que ce que j'utilise réellement. Merci :) –

1

Gardez une perspective de haut niveau. Le problème est que OpenCV n'est pas assez rapide pour chercher dans la vidéo source. Cela pourrait être dû au fait

  • Codecs ne sont pas la force de OpenCV
  • La vidéo source n'est pas encodées pour efficace la recherche

la machine Vous a beaucoup de matériel graphique dédiés à l'effet de levier, mais il n'a pas capacités spécialisées pour la recherche aléatoire dans un ensemble de données de 17 Go, que ce soit un fichier, une base de données ou un ensemble de fichiers. Le disque prendra quelques millisecondes par recherche. Ce sera mieux pour un SSD mais pas encore si génial. Ensuite, vous attendez qu'il charge dans la mémoire principale et vous devez générer toutes ces données en premier lieu.

Utilisez ffmpeg, qui devrait gérer le décodage très efficacement, peut-être même en utilisant le GPU. Voici un tutorial. (Disclaimer, je ne l'ai pas utilisé moi-même.)

Vous pouvez prétraiter la vidéo pour ajouter des images clés. En principe, cela ne devrait pas nécessiter un réencodage complet, au moins pour MPEG, mais je ne connais pas grand-chose des détails. MJPEG transforme essentiellement toutes les images en images clés, mais vous pouvez trouver un terrain d'entente et peut-être chercher 1,5 fois plus vite à un coût de taille 2x. Mais évitez de frapper le disque. En ce qui concerne SQLite, c'est une bonne solution au problème de la recherche dans 17 Go de données. La notion que les bases de données ne sont pas optimisées pour l'accès aléatoire est poppycock. Bien sûr qu'ils le sont. Un système de fichiers est une sorte de base de données. L'accès aléatoire en 17 Go est lent à cause du matériel, pas de logiciel.

Je recommande de ne pas utiliser le système de fichiers pour cette tâche, car il s'agit d'une ressource partagée synchronisée avec le reste de la machine. En outre, la création d'un demi-million de fichiers (et leur suppression une fois terminé) prendra beaucoup de temps. C'est pas pour quoi un système de fichiers est spécialisé. Vous pouvez contourner cela, cependant, en stockant plusieurs images dans chaque fichier. Mais alors vous avez besoin d'un format pour trouver l'image désirée, et alors pourquoi ne pas les mettre tous dans un fichier?

En effet, (si vous allez sur la route de 17 Go) pourquoi ne pas ignorer l'ensemble du problème et tout mettre en mémoire virtuelle? VM est tout aussi bon pour faire la recherche de disque comme SQLite ou le système de fichiers. Tant que le système d'exploitation sait que le processus peut utiliser autant de mémoire et que vous utilisez des pointeurs 64 bits, cela devrait être une bonne solution et la première chose à faire.

+0

Malheureusement, mon application a des dépendances 32 bits et je ne peux pas passer en 64bits donc la solution VM n'est pas appropriée. Le temps de recherche actuel est ~ 30ms. J'espère que les deux SQLite et système de fichiers peuvent battre cela, même en tenant compte de la limitation matérielle (accès au disque ~ 10ms à droite?) –

+0

@ FrédéricTerrazzoni 30 ms est rapidement comparé au taux de rafraîchissement de 40 ms d'une vidéo 25fps un bug dans la bibliothèque. Néanmoins, vous devriez essayer ffmpeg, il pourrait être beaucoup plus rapide. (Je suppose que vous avez initialement tout le fichier vidéo de 500 Mo, au moins dans le cache disque, ce qui reflète vraiment le temps de traitement.L'accès au disque devrait être de ~ 5-8 ms, la lecture de 40 Ko à 20 Mo/s serait de 2 ms, et vous avez alors la décompression JPEG, que vous pouvez mesurer avant de vous lancer dans la réécriture. – Potatoswatter

+0

@ FrédéricTerrazzoni Si 30 ms le temps de recherche * dans MJPEG * en utilisant OpenCV sur le fichier de 1,7 Go, vous avez potentiellement peu à gagner de tout cela. Si vous n'entendez pas physiquement le disque, les données sont déjà dans la RAM. Le seul goulot d'étranglement est la décompression MJPEG, qui est exactement la même que la recherche d'un cadre (en utilisant SQLite ou NTFS ou autre) et en effectuant une décompression JPEG. Dans ce cas, vous avez certainement besoin d'un décompresseur plus rapide. – Potatoswatter

Questions connexes