Utiliser ffmpeg pour exploiter le flux d'une caméra IP
Alors pour ceux qui cherchent un outil performant pour visualiser des flux vidéo provenant d'une caméra, il faut se pencher sur ffmpeg.
https://ffmpeg.org/download.html
ça s'installe sur Linux, Windows, etc. et permet de lire un flux avec RTSP.
Avantage : hyper-réactif, même à travers un VPN. le flux s'affiche en un instant.
Un exemple de code avec 3 caméras:
@echo off start "" ffplay -rtsp_transport tcp -fflags nobuffer -flags low_delay -probesize 32 -an "rtsp://admin:camera79@192.168.1.201:554" start "" ffplay -rtsp_transport tcp -fflags nobuffer -flags low_delay -probesize 32 -an "rtsp://admin:camera79@192.168.1.200/11" start "" ffplay -rtsp_transport tcp -fflags nobuffer -flags low_delay -probesize 32 -an "rtsp://192.168.1.202:554"
A adapter pour chaque caméra.
Sous Win, il faut juste compléter le PATH pour trouver les exécutables, il y en a trois : ffmpeg, ffplay, ffprobe. C'est le second qu'on utilise pour visualiser le flux.
Pour aller plus loin, voici un script .bat qui enregistre des vidéos en fichiers mp4,
@echo off
setlocal enabledelayedexpansion
REM Dossier d'enregistrement
set BASEDIR=C:\RTSP_RECORDS\cam1
mkdir "%BASEDIR%" 2>nul
set SEGMENT_DURATION=60
set FILE_LIFETIME=3600
:LOOP
REM Création d'un horodatage propre YYYYMMDD_HHMMSS
for /f %%A in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmmss"') do set TIMESTAMP=%%A
set FILENAME=%BASEDIR%\cam1_%TIMESTAMP%.mp4
REM Enregistrement d'un segment vidéo
ffmpeg -rtsp_transport tcp -fflags nobuffer -i "rtsp://192.168.1.10:554/stream1" -c:v copy -an -t %SEGMENT_DURATION% "%FILENAME%"
REM Purge des fichiers plus vieux que FILE_LIFETIME secondes
powershell -Command "Get-ChildItem '%BASEDIR%\cam1_*.mp4' | Where-Object { ($_.CreationTimeUtc -lt (Get-Date).ToUniversalTime().AddSeconds(-%FILE_LIFETIME%)) } | Remove-Item"
goto LOOP
Ensuite on peut utiliser VLC ou SMPlayer par exemple pour relire les fichiers du dossier ainsi constitué.
Alternative avec un script powershell, qu'on peut installer ensuite comme service windows
# ==============================
# RTSP Recorder - PowerShell
# Version robuste avec reconnexion et log centralisé
# Avec traces détaillées
# ==============================
$BaseDir = "C:\RTSP_RECORDS\cam1"
$SegmentDuration = 600 # 10 minutes
$FileLifetime = 36000 # 10 heures
$RTSP_URL = "rtsp://192.168.1.10:554/stream1"
$FFmpegPath = "C:\ffmpeg\bin\ffmpeg.exe"
$RetryDelay = 10 # secondes avant de réessayer
$FFmpegTimeout = 30 # secondes timeout connexion ffmpeg
$LogFile = Join-Path $BaseDir "ffmpeg.log"
# ------------------------------
# Fonction de log formatée (correcte)
# ------------------------------
function Log($msg) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $LogFile -Value "[$timestamp] $msg"
}
# ------------------------------
# Création du dossier si inexistant
# ------------------------------
if (!(Test-Path $BaseDir)) {
New-Item -ItemType Directory -Path $BaseDir | Out-Null
Log "Création du dossier $BaseDir"
} else {
Log "Dossier existant : $BaseDir"
}
# ------------------------------
# Création du fichier log si inexistant
# ------------------------------
if (!(Test-Path $LogFile)) {
New-Item -Path $LogFile -ItemType File | Out-Null
Log "Création du fichier de log : $LogFile"
} else {
Log "Fichier de log existant : $LogFile"
}
# ------------------------------
# Fonction pour tester si le flux RTSP est disponible
# ------------------------------
function Test-RTSP {
param ([string]$url)
try {
$uri = [System.Uri]$url
Log "Test RTSP sur $($uri.Host):$($uri.Port)"
$tcp = New-Object System.Net.Sockets.TcpClient
$async = $tcp.BeginConnect($uri.Host, $uri.Port, $null, $null)
$wait = $async.AsyncWaitHandle.WaitOne(3000) # timeout 3s
if (-not $wait) {
Log "RTSP → échec : timeout"
return $false
}
$tcp.EndConnect($async)
$tcp.Close()
Log "RTSP → OK"
return $true
}
catch {
Log "Erreur Test-RTSP : $_"
return $false
}
}
# ------------------------------
# Boucle infinie
# ------------------------------
Log "Service RTSP Recorder démarré"
while ($true) {
Log "Début boucle principale"
if (Test-RTSP -url $RTSP_URL) {
$timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss")
$file = Join-Path $BaseDir "cam1_$timestamp.mp4"
Log "Démarrage enregistrement : $file"
$args = @(
"-rtsp_transport", "tcp",
"-fflags", "nobuffer",
"-timeout", ($FFmpegTimeout * 1000000), # microsecondes
"-i", $RTSP_URL,
"-c:v", "copy",
"-an",
"-t", $SegmentDuration,
$file
)
try {
Log "Lancement ffmpeg..."
$proc = Start-Process -FilePath $FFmpegPath -ArgumentList $args -NoNewWindow -PassThru
$proc.WaitForExit()
Log "ffmpeg terminé (code $($proc.ExitCode))"
if ($proc.ExitCode -ne 0) {
Log "Erreur ffmpeg - attente $RetryDelay sec"
Start-Sleep -Seconds $RetryDelay
}
else {
Log "Segment enregistré : $file"
}
}
catch {
Log "Exception ffmpeg : $_"
Log "Pause $RetryDelay sec"
Start-Sleep -Seconds $RetryDelay
}
# ----------------------
# Purge des fichiers anciens
# ----------------------
Log "Purge des anciens fichiers..."
$limit = (Get-Date).AddSeconds(-$FileLifetime)
$oldFiles = Get-ChildItem $BaseDir -Filter "cam1_*.mp4" |
Where-Object { $_.CreationTime -lt $limit }
foreach ($f in $oldFiles) {
Log "Suppression : $($f.FullName)"
Remove-Item $f.FullName -Force
}
Log "Purge terminée"
}
else {
Log "RTSP indisponible, retry dans $RetryDelay sec"
Start-Sleep -Seconds $RetryDelay
}
Log "Fin boucle - pause 0.5 sec"
Start-Sleep -Milliseconds 500
}
Création d'un service (notes rapides)
telecharger nssm et l’installer
créer un path vers le binaire nssm
créer le service “RTSP-Recorder” en précisant le path du script (C:\RTSP_RECORDS\recorder.ps1), les paramètres, le répertoire de démarrage
nssm install RTSP-Recorder
une fois créé, le lancer (tjs en powershell admin)
nssm start RTSP-Recorder
Vérifier que le service fonctionne
Get-Service RTSP-Recorder
Status Name DisplayName
---- -----------
Running RTSP-Recorder RTSP-Recorder
si modif du script alors, pour prendre en compte les modifs,
nssm stop RTSP-Recorder
nssm start RTSP-Recorder