New upstream version 18.0.1+dfsg1
This commit is contained in:
parent
6efda2859e
commit
f2cf6cce50
1337 changed files with 41178 additions and 84670 deletions
|
|
@ -3,6 +3,7 @@ FFmpegAAC="ترميز AAC الافتراضي لـFFmpeg"
|
|||
Bitrate="معدل النقل"
|
||||
Preset="الإعداد المسبق"
|
||||
|
||||
|
||||
NVENC.Preset.default="الإفتراضي"
|
||||
NVENC.Preset.hq="جودة عالية"
|
||||
NVENC.Preset.hp="أداء عالي"
|
||||
|
|
@ -25,3 +26,4 @@ MediaFileFilter.VideoFiles="ملفات الفيديو"
|
|||
MediaFileFilter.AudioFiles="ملفات الصوت"
|
||||
MediaFileFilter.AllFiles="كل الملفات"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,3 +5,5 @@ Bitrate="Битрейт"
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Control de freqüència"
|
|||
KeyframeIntervalSec="Interval de fotograma clau (en segons, 0 = automàtic)"
|
||||
Lossless="Sense pèrdues"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Utilitza codificació en dues passades"
|
||||
NVENC.Preset.default="Per defecte"
|
||||
NVENC.Preset.hq="Alta Qualitat"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Arxius de vídeo"
|
|||
MediaFileFilter.AudioFiles="Arxius d'àudio"
|
||||
MediaFileFilter.AllFiles="Tots els fitxers"
|
||||
|
||||
ReplayBuffer="Memòria intermèdia de reproducció"
|
||||
ReplayBuffer.Save="Desa la repetició"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Řízení toku"
|
|||
KeyframeIntervalSec="Interval klíč. snímků (vteřiny, 0=auto)"
|
||||
Lossless="Lossless"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Použít dvoustupňové enkódování"
|
||||
NVENC.Preset.default="Výchozí"
|
||||
NVENC.Preset.hq="Vysoká kvalita"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Video soubory"
|
|||
MediaFileFilter.AudioFiles="Zvukové soubory"
|
||||
MediaFileFilter.AllFiles="Všechny soubory"
|
||||
|
||||
ReplayBuffer="Záznam do paměti"
|
||||
ReplayBuffer.Save="Uložit záznam"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,54 @@
|
|||
FFmpegOutput="FFmpeg Output"
|
||||
FFmpegAAC="FFmpeg Standard AAC Encoder"
|
||||
Bitrate="Bitrate"
|
||||
Preset="Forudindstillet"
|
||||
RateControl="Tempokontrol"
|
||||
KeyframeIntervalSec="Keyframe-interval (sekunder, 0= auto)"
|
||||
Lossless="Tabsfri"
|
||||
|
||||
BFrames="B-rammer"
|
||||
|
||||
NVENC.Use2Pass="Benyt to-trins kodning"
|
||||
NVENC.Preset.default="Standard"
|
||||
NVENC.Preset.hq="Høj kvalitet"
|
||||
NVENC.Preset.hp="Høj ydeevne"
|
||||
NVENC.Preset.bd="BluRay"
|
||||
NVENC.Preset.ll="Lav latens"
|
||||
NVENC.Preset.llhq="Lav-latens høj kvalitet"
|
||||
NVENC.Preset.llhp="Lav latens høj ydeevne"
|
||||
NVENC.Level="Niveau"
|
||||
|
||||
FFmpegSource="Mediekilde"
|
||||
LocalFile="Lokal fil"
|
||||
Looping="Gentagelse"
|
||||
Input="Input"
|
||||
InputFormat="Input format"
|
||||
ForceFormat="Gennemtving-formatkonvertering"
|
||||
HardwareDecode="Brug hardwareafkodning når tilgængelige"
|
||||
ClearOnMediaEnd="Skjul kilde når afspilning slutter"
|
||||
Advanced="Avanceret"
|
||||
AudioBufferSize="Audio bufferstørrelse (frames)"
|
||||
VideoBufferSize="Video bufferstørrelse (frames)"
|
||||
FrameDropping="Billedtabsniveau"
|
||||
DiscardNone="Ingen"
|
||||
DiscardDefault="Standard (ugyldige pakker)"
|
||||
DiscardNonRef="Ikke-reference billeder"
|
||||
DiscardBiDir="Tovejs frames"
|
||||
DiscardNonIntra="Non-Intra frames"
|
||||
DiscardNonKey="Non-Key Frames"
|
||||
DiscardAll="Alle frames (pas på!)"
|
||||
RestartWhenActivated="Genstart afspilning når kilde bliver aktiv"
|
||||
ColorRange="YUV-farveområde"
|
||||
ColorRange.Auto="Auto"
|
||||
ColorRange.Partial="Delvis"
|
||||
ColorRange.Full="Fuld"
|
||||
|
||||
|
||||
MediaFileFilter.AllMediaFiles="Alle mediefiler"
|
||||
MediaFileFilter.VideoFiles="Videofiler"
|
||||
MediaFileFilter.AudioFiles="Lydfiler"
|
||||
MediaFileFilter.AllFiles="Alle filer"
|
||||
|
||||
ReplayBuffer="Genafspilningsbuffer"
|
||||
ReplayBuffer.Save="Gem Genafspilning"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
FFmpegOutput="FFmpeg Ausgabe"
|
||||
FFmpegAAC="FFmpeg Standard AAC Encoder"
|
||||
FFmpegAAC="FFmpeg Standard AAC Codierer"
|
||||
Bitrate="Bitrate"
|
||||
Preset="Voreinstellung"
|
||||
RateControl="Qualitäts Regulierungsmethode"
|
||||
KeyframeIntervalSec="Keyframeintervall (Sekunden, 0=auto)"
|
||||
Lossless="Verlustfrei"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Benutze Two-Pass Encoding"
|
||||
NVENC.Preset.default="Standard"
|
||||
NVENC.Preset.hq="Hohe Qualität"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Video-Dateien"
|
|||
MediaFileFilter.AudioFiles="Audio-Dateien"
|
||||
MediaFileFilter.AllFiles="Alle Dateien"
|
||||
|
||||
ReplayBuffer="Replaypuffer"
|
||||
ReplayBuffer.Save="Replay speichern"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ FFmpegAAC="FFmpeg προεπιλεγμένος κωδικοποιητής AAC"
|
|||
Bitrate="Ρυθμός μετάδοσης bit"
|
||||
|
||||
|
||||
NVENC.Preset.default="Προεπιλογή"
|
||||
|
||||
LocalFile="Τοπικό αρχείο"
|
||||
Looping="Επανάληψη"
|
||||
Input="Είσοδος"
|
||||
|
|
@ -18,3 +20,4 @@ DiscardAll="Όλα τα καρέ (Προσοχή!)"
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,3 +48,6 @@ MediaFileFilter.AllMediaFiles="All Media Files"
|
|||
MediaFileFilter.VideoFiles="Video Files"
|
||||
MediaFileFilter.AudioFiles="Audio Files"
|
||||
MediaFileFilter.AllFiles="All Files"
|
||||
|
||||
ReplayBuffer="Replay Buffer"
|
||||
ReplayBuffer.Save="Save Replay"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Control de la frecuencia"
|
|||
KeyframeIntervalSec="Intervalo de keyframes (segundos, 0=auto)"
|
||||
Lossless="Sin pérdidas"
|
||||
|
||||
BFrames="B-Frames"
|
||||
|
||||
NVENC.Use2Pass="Usar codificación en dos pasadas"
|
||||
NVENC.Preset.default="Por defecto"
|
||||
NVENC.Preset.hq="Alta Calidad"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Archivos de vídeo"
|
|||
MediaFileFilter.AudioFiles="Archivos de audio"
|
||||
MediaFileFilter.AllFiles="Todos los Archivos"
|
||||
|
||||
ReplayBuffer="Búfer de reproducción"
|
||||
ReplayBuffer.Save="Guardar repetición"
|
||||
|
||||
|
|
|
|||
34
plugins/obs-ffmpeg/data/locale/et-EE.ini
Normal file
34
plugins/obs-ffmpeg/data/locale/et-EE.ini
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
FFmpegOutput="FFmpeg väljund"
|
||||
Bitrate="Bitikiirus"
|
||||
|
||||
|
||||
NVENC.Preset.default="Vaikimisi"
|
||||
NVENC.Preset.hq="Kõrge kvaliteet"
|
||||
NVENC.Preset.hp="Suur jõudlus"
|
||||
NVENC.Preset.bd="Bluray"
|
||||
NVENC.Preset.ll="Madal-viivitus"
|
||||
NVENC.Preset.llhq="Madal-viivitus Kõrge kvaliteediga"
|
||||
NVENC.Preset.llhp="Madal-viivitus suure jõudlusega"
|
||||
NVENC.Level="Tase"
|
||||
|
||||
FFmpegSource="Meedia allikas"
|
||||
LocalFile="Kohalik fail"
|
||||
Looping="Korda"
|
||||
Input="Sisend"
|
||||
InputFormat="Sisestus formaat"
|
||||
ClearOnMediaEnd="Peida allikas kui taasesitus lõppeb"
|
||||
AudioBufferSize="Audio puhvri suurus (kaadrit)"
|
||||
ColorRange="YUV värviruumi vahemik"
|
||||
ColorRange.Auto="Automaatne"
|
||||
ColorRange.Partial="Osaline"
|
||||
ColorRange.Full="Täielik"
|
||||
|
||||
|
||||
MediaFileFilter.AllMediaFiles="Kõik meediumifailid"
|
||||
MediaFileFilter.VideoFiles="Videofailid"
|
||||
MediaFileFilter.AudioFiles="Helifailid"
|
||||
MediaFileFilter.AllFiles="Kõik failid"
|
||||
|
||||
ReplayBuffer="Taasesituse puhver"
|
||||
ReplayBuffer.Save="Salvesta Taasesitus"
|
||||
|
||||
|
|
@ -6,6 +6,8 @@ RateControl="Tasaren kontrola"
|
|||
KeyframeIntervalSec="Gako-fotogramen tartea (segundoak, 0=auto)"
|
||||
Lossless="Galerarik gabe"
|
||||
|
||||
BFrames="B-fotogramak"
|
||||
|
||||
NVENC.Use2Pass="Erabili bi urratseko kodeketa"
|
||||
NVENC.Preset.default="Lehenetsia"
|
||||
NVENC.Preset.hq="Kalitate handia"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Bideo-fitxategiak"
|
|||
MediaFileFilter.AudioFiles="Audio-fitxategiak"
|
||||
MediaFileFilter.AllFiles="Fitxategi guztiak"
|
||||
|
||||
ReplayBuffer="Erreprodukzio bufferra"
|
||||
ReplayBuffer.Save="Gorde erreprodukzioa"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Rate Control -tila"
|
|||
KeyframeIntervalSec="Keyframe-väli (sekunteina, 0=automaattinen)"
|
||||
Lossless="Häviötön"
|
||||
|
||||
BFrames="B-kehykset"
|
||||
|
||||
NVENC.Use2Pass="Käytä Two-Pass enkoodausta"
|
||||
NVENC.Preset.default="Oletusarvo"
|
||||
NVENC.Preset.hq="Korkea laatu"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Videotiedostot"
|
|||
MediaFileFilter.AudioFiles="Äänitiedostot"
|
||||
MediaFileFilter.AllFiles="Kaikki tiedostot"
|
||||
|
||||
ReplayBuffer="Toistopuskuri"
|
||||
ReplayBuffer.Save="Tallenna uusinta"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Contrôle du débit"
|
|||
KeyframeIntervalSec="Intervalle d'image-clé (en secondes, 0 = auto)"
|
||||
Lossless="Sans perte"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Utiliser l'encodage double passe"
|
||||
NVENC.Preset.default="Défaut"
|
||||
NVENC.Preset.hq="Haute qualité"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Fichiers vidéo"
|
|||
MediaFileFilter.AudioFiles="Fichiers audio"
|
||||
MediaFileFilter.AllFiles="Tous les fichiers"
|
||||
|
||||
ReplayBuffer="Tampon de relecture"
|
||||
ReplayBuffer.Save="Sauvegarder la relecture"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ FFmpegOutput="Saída de FFmpeg"
|
|||
FFmpegAAC="Codificador AAC FFmpeg predefinido"
|
||||
Bitrate="Velocidade de bits"
|
||||
|
||||
|
||||
NVENC.Level="Nivel"
|
||||
|
||||
FFmpegSource="Fonte multimedia"
|
||||
|
|
@ -24,3 +25,4 @@ DiscardAll="Todos os marcos (con tino!)"
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="בקרת קצב"
|
|||
KeyframeIntervalSec="מרווח ערך ה keyframe בשניות (0=אוטומטי)"
|
||||
Lossless="ללא אובדן נתונים"
|
||||
|
||||
|
||||
NVENC.Use2Pass="השתמש בקידוד שני מעברים"
|
||||
NVENC.Preset.default="ברירת מחדל"
|
||||
NVENC.Preset.hq="איכות גבוהה"
|
||||
|
|
@ -47,3 +48,4 @@ MediaFileFilter.VideoFiles="קבצי וידאו"
|
|||
MediaFileFilter.AudioFiles="קבצי אודיו"
|
||||
MediaFileFilter.AllFiles="כל הקבצים"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="Kontrola protoka"
|
|||
KeyframeIntervalSec="Interval ključnih frejmova (sekunde, 0=automatski)"
|
||||
Lossless="Bez gubitka"
|
||||
|
||||
|
||||
NVENC.Use2Pass="Koristi enkoding duplog prolaza"
|
||||
NVENC.Preset.default="Podrazumevani"
|
||||
NVENC.Preset.hq="Visoki kvalitet"
|
||||
|
|
@ -47,3 +48,4 @@ MediaFileFilter.VideoFiles="Video datoteke"
|
|||
MediaFileFilter.AudioFiles="Zvučne datoteke"
|
||||
MediaFileFilter.AllFiles="Sve datoteke"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
FFmpegOutput="FFmpeg kimenet"
|
||||
FFmpegAAC="FFmpeg alapértelmezett AAC kódoló"
|
||||
Bitrate="Bitráta"
|
||||
Bitrate="Bitsebesség"
|
||||
Preset="Készlet"
|
||||
RateControl="Sebesség Vezérlés"
|
||||
KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
|
||||
Lossless="Veszteségmentes"
|
||||
|
||||
BFrames="B képkocka"
|
||||
|
||||
NVENC.Use2Pass="Kétmenetes kódolás"
|
||||
NVENC.Preset.default="Alapértelmezett"
|
||||
NVENC.Preset.hq="Kiváló minőség"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Videofájlok"
|
|||
MediaFileFilter.AudioFiles="Hangfájlok"
|
||||
MediaFileFilter.AllFiles="Minden fájl"
|
||||
|
||||
ReplayBuffer="Visszajátszás puffer"
|
||||
ReplayBuffer.Save="Visszajátszás mentése"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Controllo frequenza"
|
|||
KeyframeIntervalSec="Intervallo Keyframe (secondi, 0=automatico)"
|
||||
Lossless="Lossless"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Usa codifica in due passaggi"
|
||||
NVENC.Preset.default="Predefinito"
|
||||
NVENC.Preset.hq="Alta Qualità"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="File video"
|
|||
MediaFileFilter.AudioFiles="File audio"
|
||||
MediaFileFilter.AllFiles="Tutti i file"
|
||||
|
||||
ReplayBuffer="Buffer di Replay"
|
||||
ReplayBuffer.Save="Salva Replay"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="レート制御"
|
|||
KeyframeIntervalSec="キーフレーム間隔 (秒, 0=自動)"
|
||||
Lossless="無損失"
|
||||
|
||||
BFrames="B-フレーム"
|
||||
|
||||
NVENC.Use2Pass="2パスエンコードを使用"
|
||||
NVENC.Preset.default="既定"
|
||||
NVENC.Preset.hq="高品質"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="ビデオファイル"
|
|||
MediaFileFilter.AudioFiles="オーディオファイル"
|
||||
MediaFileFilter.AllFiles="すべてのファイル"
|
||||
|
||||
ReplayBuffer="リプレイバッファー"
|
||||
ReplayBuffer.Save="リプレイ保存"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="데이터율 제어"
|
|||
KeyframeIntervalSec="키프레임 간격 (초 단위, 0=자동)"
|
||||
Lossless="무손실"
|
||||
|
||||
BFrames="B-화면"
|
||||
|
||||
NVENC.Use2Pass="2 패스 인코딩 사용"
|
||||
NVENC.Preset.default="기본"
|
||||
NVENC.Preset.hq="우수한 품질"
|
||||
|
|
@ -27,7 +29,7 @@ ClearOnMediaEnd="재생이 끝나면 소스를 숨기기"
|
|||
Advanced="고급"
|
||||
AudioBufferSize="오디오 버퍼 크기 (프레임)"
|
||||
VideoBufferSize="비디오 버퍼 크기 (프레임)"
|
||||
FrameDropping="프레임 드롭 수준"
|
||||
FrameDropping="프레임 손실 수준"
|
||||
DiscardNone="없음"
|
||||
DiscardDefault="기본 (유효하지 않은 패킷)"
|
||||
DiscardNonRef="비 참조 프레임"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="비디오 파일"
|
|||
MediaFileFilter.AudioFiles="오디오 파일"
|
||||
MediaFileFilter.AllFiles="모든 파일"
|
||||
|
||||
ReplayBuffer="리플레이 버퍼"
|
||||
ReplayBuffer.Save="리플레이 저장"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="Hastighetskontroll"
|
|||
KeyframeIntervalSec="Nøkkelbildeintervall (sekunder, 0 = automatisk)"
|
||||
Lossless="Tapsfri"
|
||||
|
||||
|
||||
NVENC.Use2Pass="Bruk tostegskoding"
|
||||
NVENC.Preset.default="Standard"
|
||||
NVENC.Preset.hq="Høy kvalitet"
|
||||
|
|
@ -47,3 +48,4 @@ MediaFileFilter.VideoFiles="Videofiler"
|
|||
MediaFileFilter.AudioFiles="Lydfiler"
|
||||
MediaFileFilter.AllFiles="Alle filer"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Rate Control"
|
|||
KeyframeIntervalSec="Tijd tussen keyframes (seconden, 0=auto)"
|
||||
Lossless="Lossless"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Gebruik two-pass encoding"
|
||||
NVENC.Preset.default="Standaard"
|
||||
NVENC.Preset.hq="Hoge kwaliteit"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Videobestanden"
|
|||
MediaFileFilter.AudioFiles="Audiobestanden"
|
||||
MediaFileFilter.AllFiles="Alle bestanden"
|
||||
|
||||
ReplayBuffer="Replay Buffer"
|
||||
ReplayBuffer.Save="Replay Opslaan"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Typ przepływności"
|
|||
KeyframeIntervalSec="Odstęp między klatkami kluczowymi (sekundy, 0=automatyczny)"
|
||||
Lossless="Bezstratny"
|
||||
|
||||
BFrames="B-ramki"
|
||||
|
||||
NVENC.Use2Pass="Użyj enkodowania dwuprzebiegowego"
|
||||
NVENC.Preset.default="Domyślny"
|
||||
NVENC.Preset.hq="Wysoka jakość"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Pliki video"
|
|||
MediaFileFilter.AudioFiles="Pliki audio"
|
||||
MediaFileFilter.AllFiles="Wszystkie pliki"
|
||||
|
||||
ReplayBuffer="Bufor replay"
|
||||
ReplayBuffer.Save="Zapisz replay"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Controle da Taxa de Bits"
|
|||
KeyframeIntervalSec="Intervalo de Keyframe (segundos, 0=auto)"
|
||||
Lossless="Sem perdas"
|
||||
|
||||
BFrames="B-frames"
|
||||
|
||||
NVENC.Use2Pass="Utilizar a codificação em dois passos"
|
||||
NVENC.Preset.default="Padrão"
|
||||
NVENC.Preset.hq="Alta Qualidade"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Arquivos de Vídeo"
|
|||
MediaFileFilter.AudioFiles="Arquivos de Áudio"
|
||||
MediaFileFilter.AllFiles="Todos os Arquivos"
|
||||
|
||||
ReplayBuffer="Buffer do Replay"
|
||||
ReplayBuffer.Save="Salvar Replay"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="Controle de Taxa"
|
|||
KeyframeIntervalSec="Intervalo do keyframe (segundos, 0=automático)"
|
||||
Lossless="Sem perdas"
|
||||
|
||||
|
||||
NVENC.Preset.default="Predefinido"
|
||||
NVENC.Preset.hq="Alta Qualidade"
|
||||
NVENC.Preset.hp="Alto Desempenho"
|
||||
|
|
@ -46,3 +47,4 @@ MediaFileFilter.VideoFiles="Arquivos de Vídeo"
|
|||
MediaFileFilter.AudioFiles="Arquivos de Áudio"
|
||||
MediaFileFilter.AllFiles="Todos os ficheiros"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ FFmpegAAC="Codificator AAC implicit FFmpeg"
|
|||
Bitrate="Rată de biți"
|
||||
Preset="Presetare"
|
||||
|
||||
|
||||
NVENC.Preset.default="Implicită"
|
||||
NVENC.Preset.bd="Bluray"
|
||||
NVENC.Level="Nivel"
|
||||
|
|
@ -38,3 +39,4 @@ MediaFileFilter.VideoFiles="Fișiere video"
|
|||
MediaFileFilter.AudioFiles="Fișiere audio"
|
||||
MediaFileFilter.AllFiles="Toate fișierele"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Управление битрейтом"
|
|||
KeyframeIntervalSec="Интервал ключевых кадров (сек, 0=авто)"
|
||||
Lossless="Без потерь"
|
||||
|
||||
BFrames="B-Кадры"
|
||||
|
||||
NVENC.Use2Pass="Использовать двухпроходное кодирование"
|
||||
NVENC.Preset.default="По умолчанию"
|
||||
NVENC.Preset.hq="Высокое качество"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Видеофайлы"
|
|||
MediaFileFilter.AudioFiles="Аудиофайлы"
|
||||
MediaFileFilter.AllFiles="Все файлы"
|
||||
|
||||
ReplayBuffer="Буфер повтора"
|
||||
ReplayBuffer.Save="Сохранить повтор"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ FFmpegAAC="Predvolený FFmpeg AAC enkodér"
|
|||
Bitrate="Bitrate"
|
||||
|
||||
|
||||
|
||||
Looping="Slučka"
|
||||
Advanced="Rozšírené"
|
||||
DiscardNone="Žiadny"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ FFmpegAAC="FFmpeg Prevzeti AAC Encoder"
|
|||
Bitrate="Bitrate"
|
||||
|
||||
|
||||
|
||||
FFmpegSource="Medijski Vir"
|
||||
LocalFile="Lokalna Datoteka"
|
||||
Looping="Ponavljaj"
|
||||
|
|
@ -25,3 +26,4 @@ DiscardAll="Vse Frame (Pazite!)"
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="Kontrola protoka"
|
|||
KeyframeIntervalSec="Interval ključnih frejmova (sekunde, 0=automatski)"
|
||||
Lossless="Bez gubitka"
|
||||
|
||||
|
||||
NVENC.Use2Pass="Koristi enkoding duplog prolaza"
|
||||
NVENC.Preset.default="Podrazumevani"
|
||||
NVENC.Preset.hq="Visoki kvalitet"
|
||||
|
|
@ -47,3 +48,4 @@ MediaFileFilter.VideoFiles="Video datoteke"
|
|||
MediaFileFilter.AudioFiles="Zvučne datoteke"
|
||||
MediaFileFilter.AllFiles="Sve datoteke"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ RateControl="Контрола протока"
|
|||
KeyframeIntervalSec="Интервал кључних фрејмова (секунде, 0=аутоматски)"
|
||||
Lossless="Без губитка"
|
||||
|
||||
|
||||
NVENC.Use2Pass="Користи енкодинг дуплог пролаза"
|
||||
NVENC.Preset.default="Подразумевани"
|
||||
NVENC.Preset.hq="Високи квалитет"
|
||||
|
|
@ -47,3 +48,4 @@ MediaFileFilter.VideoFiles="Видео датотеке"
|
|||
MediaFileFilter.AudioFiles="Звучне датотеке"
|
||||
MediaFileFilter.AllFiles="Све датотеке"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Hastighetskontroll"
|
|||
KeyframeIntervalSec="Intervall för keyframes (sekunder, 0=automatisk)"
|
||||
Lossless="Förlustfri"
|
||||
|
||||
BFrames="B-bildrutor"
|
||||
|
||||
NVENC.Use2Pass="Använd tvåpassavkodning"
|
||||
NVENC.Preset.default="Standard"
|
||||
NVENC.Preset.hq="Hög kvalitet"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Videofiler"
|
|||
MediaFileFilter.AudioFiles="Ljudfiler"
|
||||
MediaFileFilter.AllFiles="Alla filer"
|
||||
|
||||
ReplayBuffer="Reprisbuffert"
|
||||
ReplayBuffer.Save="Spara repris"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,5 @@ Bitrate="บิตเรท"
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,21 @@ FFmpegOutput="FFmpeg Çıkışı"
|
|||
FFmpegAAC="FFmpeg Varsayılan AAC Kodlayıcı"
|
||||
Bitrate="Bit hızı"
|
||||
Preset="Ön Tanımlı"
|
||||
KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
|
||||
RateControl="Oran Kontrolü"
|
||||
KeyframeIntervalSec="Anahtar Kare Aralığı (saniye, 0=otomatik)"
|
||||
Lossless="Kayıpsız"
|
||||
|
||||
BFrames="B-Kareleri"
|
||||
|
||||
NVENC.Use2Pass="İki Taramalı Kodlama Kullan"
|
||||
NVENC.Preset.default="Varsayılan"
|
||||
NVENC.Preset.hq="Yüksek Kalite"
|
||||
NVENC.Preset.hp="Yüksek Performans"
|
||||
NVENC.Preset.bd="Bluray"
|
||||
NVENC.Preset.ll="Düşük Gecikme"
|
||||
NVENC.Preset.llhq="Düşük Gecikme Yüksek Kalite"
|
||||
NVENC.Preset.llhp="Düşük Gecikme Yüksek Performans"
|
||||
NVENC.Level="Seviye"
|
||||
|
||||
FFmpegSource="Ortam Kaynağı"
|
||||
LocalFile="Yerel Dosya"
|
||||
|
|
@ -27,6 +37,11 @@ DiscardBiDir="Çift-Yönlü Kareler"
|
|||
DiscardNonIntra="Intra Olmayan Kareler"
|
||||
DiscardNonKey="Anahtar Olmayan Kareler"
|
||||
DiscardAll="Tüm Kareler (Dikkatli Olun!)"
|
||||
RestartWhenActivated="Yeniden oynatmayı kaynak etkin olduğunda yeniden başlat"
|
||||
ColorRange="YUV Renk Aralığı"
|
||||
ColorRange.Auto="Otomatik"
|
||||
ColorRange.Partial="Kısmi"
|
||||
ColorRange.Full="Tam"
|
||||
|
||||
|
||||
MediaFileFilter.AllMediaFiles="Tüm Medya Dosyaları"
|
||||
|
|
@ -34,3 +49,6 @@ MediaFileFilter.VideoFiles="Video Dosyaları"
|
|||
MediaFileFilter.AudioFiles="Ses Dosyaları"
|
||||
MediaFileFilter.AllFiles="Tüm Dosyalar"
|
||||
|
||||
ReplayBuffer="Tekrar Oynatma Arabelleği"
|
||||
ReplayBuffer.Save="Yeniden Oynatmayı Kaydet"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="Керування потоком"
|
|||
KeyframeIntervalSec="Інтервал ключових кадрів (секунд, 0 = авто)"
|
||||
Lossless="Без втрат"
|
||||
|
||||
BFrames="B-кадри"
|
||||
|
||||
NVENC.Use2Pass="Використовувати двопрохідне кодування"
|
||||
NVENC.Preset.default="Стандартний"
|
||||
NVENC.Preset.hq="Висока якість"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="Відео"
|
|||
MediaFileFilter.AudioFiles="Аудіо"
|
||||
MediaFileFilter.AllFiles="Всі файли"
|
||||
|
||||
ReplayBuffer="Запис Повторів"
|
||||
ReplayBuffer.Save="Зберегти Повтор"
|
||||
|
||||
|
|
|
|||
27
plugins/obs-ffmpeg/data/locale/vi-VN.ini
Normal file
27
plugins/obs-ffmpeg/data/locale/vi-VN.ini
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
FFmpegOutput="FFmpeg đầu ra"
|
||||
FFmpegAAC="FFmpeg AAC Encoder mặc định"
|
||||
Bitrate="Bitrate"
|
||||
Preset="Mẫu thiết lập"
|
||||
RateControl="Cách kiểm soát bitrate"
|
||||
KeyframeIntervalSec="Thời gian đặt Keyframe (giây, 0=tự động)"
|
||||
Lossless="Lossless"
|
||||
|
||||
|
||||
NVENC.Use2Pass="Sử dụng 2-Pass Encoding"
|
||||
NVENC.Preset.default="Mặc định"
|
||||
NVENC.Preset.hq="Chất lượng cao"
|
||||
NVENC.Preset.hp="Hiệu suất cao"
|
||||
NVENC.Preset.bd="Bluray"
|
||||
NVENC.Preset.ll="Độ trễ thấp"
|
||||
NVENC.Preset.llhq="Độ trễ thấp chất lượng cao"
|
||||
NVENC.Preset.llhp="Độ trễ thấp hiệu suất cao"
|
||||
NVENC.Level="Cấp độ"
|
||||
|
||||
LocalFile="Tập tin cục bộ"
|
||||
Looping="Lặp lại"
|
||||
Input="Nhập"
|
||||
InputFormat="Định dạng đầu vào"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -6,6 +6,8 @@ RateControl="速率控制"
|
|||
KeyframeIntervalSec="关键帧间隔(秒, 0=自动)"
|
||||
Lossless="无损"
|
||||
|
||||
BFrames="B 帧"
|
||||
|
||||
NVENC.Use2Pass="使用 Two-Pass 编码"
|
||||
NVENC.Preset.default="默认"
|
||||
NVENC.Preset.hq="高质量"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="视频文件"
|
|||
MediaFileFilter.AudioFiles="音频文件"
|
||||
MediaFileFilter.AllFiles="所有文件"
|
||||
|
||||
ReplayBuffer="回放缓存"
|
||||
ReplayBuffer.Save="保存回放"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ RateControl="位元率控制"
|
|||
KeyframeIntervalSec="關鍵訊框間隔 (秒,0 = 自動)"
|
||||
Lossless="無損"
|
||||
|
||||
BFrames="B 訊框"
|
||||
|
||||
NVENC.Use2Pass="使用 Two-Pass 編碼"
|
||||
NVENC.Preset.default="預設"
|
||||
NVENC.Preset.hq="高品質"
|
||||
|
|
@ -47,3 +49,6 @@ MediaFileFilter.VideoFiles="影像檔"
|
|||
MediaFileFilter.AudioFiles="音效檔"
|
||||
MediaFileFilter.AllFiles="所有檔案"
|
||||
|
||||
ReplayBuffer="重播緩衝"
|
||||
ReplayBuffer.Save="儲存重播"
|
||||
|
||||
|
|
|
|||
|
|
@ -355,7 +355,8 @@ static void create_audio_stream(struct ffmpeg_mux *ffm, int idx)
|
|||
|
||||
static bool init_streams(struct ffmpeg_mux *ffm)
|
||||
{
|
||||
create_video_stream(ffm);
|
||||
if (ffm->params.has_video)
|
||||
create_video_stream(ffm);
|
||||
|
||||
if (ffm->params.tracks) {
|
||||
ffm->audio_streams =
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
|
|||
enc->context->cutoff = cutoff;
|
||||
}
|
||||
|
||||
info("bitrate: %d, channels: %d",
|
||||
info("bitrate: %" PRId64 ", channels: %d",
|
||||
enc->context->bit_rate / 1000, enc->context->channels);
|
||||
|
||||
init_sizes(enc, audio);
|
||||
|
|
@ -259,7 +259,7 @@ static obs_properties_t *aac_properties(void *unused)
|
|||
obs_properties_t *props = obs_properties_create();
|
||||
|
||||
obs_properties_add_int(props, "bitrate",
|
||||
obs_module_text("Bitrate"), 32, 320, 32);
|
||||
obs_module_text("Bitrate"), 64, 320, 32);
|
||||
return props;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,13 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include <obs-module.h>
|
||||
#include <obs-hotkey.h>
|
||||
#include <obs-avc.h>
|
||||
#include <util/dstr.h>
|
||||
#include <util/pipe.h>
|
||||
#include <util/darray.h>
|
||||
#include <util/platform.h>
|
||||
#include <util/circlebuf.h>
|
||||
#include <util/threading.h>
|
||||
#include "ffmpeg-mux/ffmpeg-mux.h"
|
||||
|
||||
|
|
@ -40,17 +44,55 @@ struct ffmpeg_muxer {
|
|||
volatile bool active;
|
||||
volatile bool stopping;
|
||||
volatile bool capturing;
|
||||
|
||||
/* replay buffer */
|
||||
struct circlebuf packets;
|
||||
int64_t cur_size;
|
||||
int64_t cur_time;
|
||||
int64_t max_size;
|
||||
int64_t max_time;
|
||||
int64_t save_ts;
|
||||
int keyframes;
|
||||
obs_hotkey_id hotkey;
|
||||
|
||||
DARRAY(struct encoder_packet) mux_packets;
|
||||
pthread_t mux_thread;
|
||||
bool mux_thread_joinable;
|
||||
volatile bool muxing;
|
||||
};
|
||||
|
||||
static const char *ffmpeg_mux_getname(void *unused)
|
||||
static const char *ffmpeg_mux_getname(void *type)
|
||||
{
|
||||
UNUSED_PARAMETER(unused);
|
||||
UNUSED_PARAMETER(type);
|
||||
return obs_module_text("FFmpegMuxer");
|
||||
}
|
||||
|
||||
static inline void replay_buffer_clear(struct ffmpeg_muxer *stream)
|
||||
{
|
||||
while (stream->packets.size > 0) {
|
||||
struct encoder_packet pkt;
|
||||
circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
|
||||
obs_encoder_packet_release(&pkt);
|
||||
}
|
||||
|
||||
circlebuf_free(&stream->packets);
|
||||
stream->cur_size = 0;
|
||||
stream->cur_time = 0;
|
||||
stream->max_size = 0;
|
||||
stream->max_time = 0;
|
||||
stream->save_ts = 0;
|
||||
stream->keyframes = 0;
|
||||
}
|
||||
|
||||
static void ffmpeg_mux_destroy(void *data)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
|
||||
replay_buffer_clear(stream);
|
||||
if (stream->mux_thread_joinable)
|
||||
pthread_join(stream->mux_thread, NULL);
|
||||
da_free(stream->mux_packets);
|
||||
|
||||
os_process_pipe_destroy(stream->pipe);
|
||||
dstr_free(&stream->path);
|
||||
bfree(stream);
|
||||
|
|
@ -103,7 +145,7 @@ static void add_video_encoder_params(struct ffmpeg_muxer *stream,
|
|||
obs_data_release(settings);
|
||||
|
||||
dstr_catf(cmd, "%s %d %d %d %d %d ",
|
||||
"h264",
|
||||
obs_encoder_get_codec(vencoder),
|
||||
bitrate,
|
||||
obs_output_get_width(stream->output),
|
||||
obs_output_get_height(stream->output),
|
||||
|
|
@ -177,7 +219,8 @@ static void add_muxer_params(struct dstr *cmd, struct ffmpeg_muxer *stream)
|
|||
dstr_free(&mux);
|
||||
}
|
||||
|
||||
static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd)
|
||||
static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd,
|
||||
const char *path)
|
||||
{
|
||||
obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output);
|
||||
obs_encoder_t *aencoders[MAX_AUDIO_MIXES];
|
||||
|
|
@ -196,7 +239,11 @@ static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd)
|
|||
dstr_init_move_array(cmd, obs_module_file(FFMPEG_MUX));
|
||||
dstr_insert_ch(cmd, 0, '\"');
|
||||
dstr_cat(cmd, "\" \"");
|
||||
|
||||
dstr_copy(&stream->path, path);
|
||||
dstr_replace(&stream->path, "\"", "\"\"");
|
||||
dstr_cat_dstr(cmd, &stream->path);
|
||||
|
||||
dstr_catf(cmd, "\" %d %d ", vencoder ? 1 : 0, num_tracks);
|
||||
|
||||
if (vencoder)
|
||||
|
|
@ -213,11 +260,18 @@ static void build_command_line(struct ffmpeg_muxer *stream, struct dstr *cmd)
|
|||
add_muxer_params(cmd, stream);
|
||||
}
|
||||
|
||||
static inline void start_pipe(struct ffmpeg_muxer *stream, const char *path)
|
||||
{
|
||||
struct dstr cmd;
|
||||
build_command_line(stream, &cmd, path);
|
||||
stream->pipe = os_process_pipe_create(cmd.array, "w");
|
||||
dstr_free(&cmd);
|
||||
}
|
||||
|
||||
static bool ffmpeg_mux_start(void *data)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
obs_data_t *settings;
|
||||
struct dstr cmd;
|
||||
const char *path;
|
||||
|
||||
if (!obs_output_can_begin_data_capture(stream->output, 0))
|
||||
|
|
@ -227,14 +281,9 @@ static bool ffmpeg_mux_start(void *data)
|
|||
|
||||
settings = obs_output_get_settings(stream->output);
|
||||
path = obs_data_get_string(settings, "path");
|
||||
dstr_copy(&stream->path, path);
|
||||
dstr_replace(&stream->path, "\"", "\"\"");
|
||||
start_pipe(stream, path);
|
||||
obs_data_release(settings);
|
||||
|
||||
build_command_line(stream, &cmd);
|
||||
stream->pipe = os_process_pipe_create(cmd.array, "w");
|
||||
dstr_free(&cmd);
|
||||
|
||||
if (!stream->pipe) {
|
||||
warn("Failed to create process pipe");
|
||||
return false;
|
||||
|
|
@ -424,3 +473,343 @@ struct obs_output_info ffmpeg_muxer = {
|
|||
.encoded_packet = ffmpeg_mux_data,
|
||||
.get_properties = ffmpeg_mux_properties
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const char *replay_buffer_getname(void *type)
|
||||
{
|
||||
UNUSED_PARAMETER(type);
|
||||
return obs_module_text("ReplayBuffer");
|
||||
}
|
||||
|
||||
static bool replay_buffer_hotkey(void *data, obs_hotkey_id id,
|
||||
obs_hotkey_t *hotkey, bool pressed)
|
||||
{
|
||||
UNUSED_PARAMETER(id);
|
||||
UNUSED_PARAMETER(hotkey);
|
||||
UNUSED_PARAMETER(pressed);
|
||||
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
if (os_atomic_load_bool(&stream->active))
|
||||
stream->save_ts = os_gettime_ns() / 1000LL;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void save_replay_proc(void *data, calldata_t *cd)
|
||||
{
|
||||
replay_buffer_hotkey(data, 0, NULL, true);
|
||||
UNUSED_PARAMETER(cd);
|
||||
}
|
||||
|
||||
static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream));
|
||||
stream->output = output;
|
||||
|
||||
stream->hotkey = obs_hotkey_register_output(output,
|
||||
"ReplayBuffer.Save",
|
||||
obs_module_text("ReplayBuffer.Save"),
|
||||
replay_buffer_hotkey, stream);
|
||||
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(output);
|
||||
proc_handler_add(ph, "void save()", save_replay_proc, stream);
|
||||
|
||||
UNUSED_PARAMETER(settings);
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void replay_buffer_destroy(void *data)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
if (stream->hotkey)
|
||||
obs_hotkey_unregister(stream->hotkey);
|
||||
ffmpeg_mux_destroy(data);
|
||||
}
|
||||
|
||||
static bool replay_buffer_start(void *data)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
|
||||
if (!obs_output_can_begin_data_capture(stream->output, 0))
|
||||
return false;
|
||||
if (!obs_output_initialize_encoders(stream->output, 0))
|
||||
return false;
|
||||
|
||||
obs_data_t *s = obs_output_get_settings(stream->output);
|
||||
stream->max_time = obs_data_get_int(s, "max_time_sec") * 1000000LL;
|
||||
stream->max_size = obs_data_get_int(s, "max_size_mb") * (1024 * 1024);
|
||||
obs_data_release(s);
|
||||
|
||||
os_atomic_set_bool(&stream->active, true);
|
||||
os_atomic_set_bool(&stream->capturing, true);
|
||||
obs_output_begin_data_capture(stream->output, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool purge_front(struct ffmpeg_muxer *stream)
|
||||
{
|
||||
struct encoder_packet pkt;
|
||||
bool keyframe;
|
||||
|
||||
circlebuf_pop_front(&stream->packets, &pkt, sizeof(pkt));
|
||||
|
||||
keyframe = pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe;
|
||||
|
||||
if (keyframe)
|
||||
stream->keyframes--;
|
||||
|
||||
if (!stream->packets.size) {
|
||||
stream->cur_size = 0;
|
||||
stream->cur_time = 0;
|
||||
} else {
|
||||
struct encoder_packet first;
|
||||
circlebuf_peek_front(&stream->packets, &first, sizeof(first));
|
||||
stream->cur_time = first.dts_usec;
|
||||
stream->cur_size -= (int64_t)pkt.size;
|
||||
}
|
||||
|
||||
obs_encoder_packet_release(&pkt);
|
||||
return keyframe;
|
||||
}
|
||||
|
||||
static inline void purge(struct ffmpeg_muxer *stream)
|
||||
{
|
||||
if (purge_front(stream)) {
|
||||
struct encoder_packet pkt;
|
||||
|
||||
for (;;) {
|
||||
circlebuf_peek_front(&stream->packets, &pkt,
|
||||
sizeof(pkt));
|
||||
if (pkt.type == OBS_ENCODER_VIDEO && pkt.keyframe)
|
||||
return;
|
||||
|
||||
purge_front(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void replay_buffer_purge(struct ffmpeg_muxer *stream,
|
||||
struct encoder_packet *pkt)
|
||||
{
|
||||
if (stream->max_size) {
|
||||
if (!stream->packets.size || stream->keyframes <= 2)
|
||||
return;
|
||||
|
||||
while ((stream->cur_size + (int64_t)pkt->size) >
|
||||
stream->max_size)
|
||||
purge(stream);
|
||||
}
|
||||
|
||||
if (!stream->packets.size || stream->keyframes <= 2)
|
||||
return;
|
||||
|
||||
while ((pkt->dts_usec - stream->cur_time) > stream->max_time)
|
||||
purge(stream);
|
||||
}
|
||||
|
||||
static void insert_packet(struct darray *array, struct encoder_packet *packet,
|
||||
int64_t video_offset, int64_t *audio_offsets,
|
||||
int64_t video_dts_offset, int64_t *audio_dts_offsets)
|
||||
{
|
||||
struct encoder_packet pkt;
|
||||
DARRAY(struct encoder_packet) packets;
|
||||
packets.da = *array;
|
||||
size_t idx;
|
||||
|
||||
obs_encoder_packet_ref(&pkt, packet);
|
||||
|
||||
if (pkt.type == OBS_ENCODER_VIDEO) {
|
||||
pkt.dts_usec -= video_offset;
|
||||
pkt.dts -= video_dts_offset;
|
||||
pkt.pts -= video_dts_offset;
|
||||
} else {
|
||||
pkt.dts_usec -= audio_offsets[pkt.track_idx];
|
||||
pkt.dts -= audio_dts_offsets[pkt.track_idx];
|
||||
pkt.pts -= audio_dts_offsets[pkt.track_idx];
|
||||
}
|
||||
|
||||
for (idx = packets.num; idx > 0; idx--) {
|
||||
struct encoder_packet *p = packets.array + (idx - 1);
|
||||
if (p->dts_usec < pkt.dts_usec)
|
||||
break;
|
||||
}
|
||||
|
||||
da_insert(packets, idx, &pkt);
|
||||
*array = packets.da;
|
||||
}
|
||||
|
||||
static void *replay_buffer_mux_thread(void *data)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
|
||||
start_pipe(stream, stream->path.array);
|
||||
|
||||
if (!stream->pipe) {
|
||||
warn("Failed to create process pipe");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!send_headers(stream)) {
|
||||
warn("Could not write headers for file '%s'",
|
||||
stream->path.array);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < stream->mux_packets.num; i++) {
|
||||
struct encoder_packet *pkt = &stream->mux_packets.array[i];
|
||||
write_packet(stream, pkt);
|
||||
obs_encoder_packet_release(pkt);
|
||||
}
|
||||
|
||||
info("Wrote replay buffer to '%s'", stream->path.array);
|
||||
|
||||
error:
|
||||
os_process_pipe_destroy(stream->pipe);
|
||||
stream->pipe = NULL;
|
||||
da_free(stream->mux_packets);
|
||||
os_atomic_set_bool(&stream->muxing, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void replay_buffer_save(struct ffmpeg_muxer *stream)
|
||||
{
|
||||
const size_t size = sizeof(struct encoder_packet);
|
||||
size_t num_packets = stream->packets.size / size;
|
||||
|
||||
da_reserve(stream->mux_packets, num_packets);
|
||||
|
||||
/* ---------------------------- */
|
||||
/* reorder packets */
|
||||
|
||||
bool found_video = false;
|
||||
bool found_audio[MAX_AUDIO_MIXES] = {0};
|
||||
int64_t video_offset = 0;
|
||||
int64_t video_dts_offset = 0;
|
||||
int64_t audio_offsets[MAX_AUDIO_MIXES] = {0};
|
||||
int64_t audio_dts_offsets[MAX_AUDIO_MIXES] = {0};
|
||||
|
||||
for (size_t i = 0; i < num_packets; i++) {
|
||||
struct encoder_packet *pkt;
|
||||
pkt = circlebuf_data(&stream->packets, i * size);
|
||||
|
||||
if (pkt->type == OBS_ENCODER_VIDEO) {
|
||||
if (!found_video) {
|
||||
video_offset = pkt->dts_usec;
|
||||
video_dts_offset = pkt->dts;
|
||||
found_video = true;
|
||||
}
|
||||
} else {
|
||||
if (!found_audio[pkt->track_idx]) {
|
||||
found_audio[pkt->track_idx] = true;
|
||||
audio_offsets[pkt->track_idx] = pkt->dts_usec;
|
||||
audio_dts_offsets[pkt->track_idx] = pkt->dts;
|
||||
}
|
||||
}
|
||||
|
||||
insert_packet(&stream->mux_packets.da, pkt,
|
||||
video_offset, audio_offsets,
|
||||
video_dts_offset, audio_dts_offsets);
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
/* generate filename */
|
||||
|
||||
obs_data_t *settings = obs_output_get_settings(stream->output);
|
||||
const char *dir = obs_data_get_string(settings, "directory");
|
||||
const char *fmt = obs_data_get_string(settings, "format");
|
||||
const char *ext = obs_data_get_string(settings, "extension");
|
||||
bool space = obs_data_get_bool(settings, "allow_spaces");
|
||||
|
||||
char *filename = os_generate_formatted_filename(ext, space, fmt);
|
||||
|
||||
dstr_copy(&stream->path, dir);
|
||||
dstr_replace(&stream->path, "\\", "/");
|
||||
if (dstr_end(&stream->path) != '/')
|
||||
dstr_cat_ch(&stream->path, '/');
|
||||
dstr_cat(&stream->path, filename);
|
||||
|
||||
bfree(filename);
|
||||
obs_data_release(settings);
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
os_atomic_set_bool(&stream->muxing, true);
|
||||
stream->mux_thread_joinable = pthread_create(&stream->mux_thread, NULL,
|
||||
replay_buffer_mux_thread, stream) == 0;
|
||||
}
|
||||
|
||||
static void deactivate_replay_buffer(struct ffmpeg_muxer *stream)
|
||||
{
|
||||
if (stopping(stream))
|
||||
obs_output_end_data_capture(stream->output);
|
||||
|
||||
os_atomic_set_bool(&stream->active, false);
|
||||
os_atomic_set_bool(&stream->sent_headers, false);
|
||||
os_atomic_set_bool(&stream->stopping, false);
|
||||
replay_buffer_clear(stream);
|
||||
}
|
||||
|
||||
static void replay_buffer_data(void *data, struct encoder_packet *packet)
|
||||
{
|
||||
struct ffmpeg_muxer *stream = data;
|
||||
struct encoder_packet pkt;
|
||||
|
||||
if (!active(stream))
|
||||
return;
|
||||
|
||||
if (stopping(stream)) {
|
||||
if (packet->sys_dts_usec >= stream->stop_ts) {
|
||||
deactivate_replay_buffer(stream);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
obs_encoder_packet_ref(&pkt, packet);
|
||||
replay_buffer_purge(stream, &pkt);
|
||||
|
||||
if (!stream->packets.size)
|
||||
stream->cur_time = pkt.dts_usec;
|
||||
stream->cur_size += pkt.size;
|
||||
|
||||
circlebuf_push_back(&stream->packets, packet, sizeof(*packet));
|
||||
|
||||
if (packet->type == OBS_ENCODER_VIDEO && packet->keyframe)
|
||||
stream->keyframes++;
|
||||
|
||||
if (stream->save_ts && packet->sys_dts_usec >= stream->save_ts) {
|
||||
if (os_atomic_load_bool(&stream->muxing))
|
||||
return;
|
||||
|
||||
if (stream->mux_thread_joinable) {
|
||||
pthread_join(stream->mux_thread, NULL);
|
||||
stream->mux_thread_joinable = false;
|
||||
}
|
||||
|
||||
stream->save_ts = 0;
|
||||
replay_buffer_save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void replay_buffer_defaults(obs_data_t *s)
|
||||
{
|
||||
obs_data_set_default_int(s, "max_time_sec", 15);
|
||||
obs_data_set_default_int(s, "max_size_mb", 500);
|
||||
obs_data_set_default_string(s, "format", "%CCYY-%MM-%DD %hh-%mm-%ss");
|
||||
obs_data_set_default_string(s, "extension", "mp4");
|
||||
obs_data_set_default_bool(s, "allow_spaces", true);
|
||||
}
|
||||
|
||||
struct obs_output_info replay_buffer = {
|
||||
.id = "replay_buffer",
|
||||
.flags = OBS_OUTPUT_AV |
|
||||
OBS_OUTPUT_ENCODED |
|
||||
OBS_OUTPUT_MULTI_TRACK,
|
||||
.get_name = replay_buffer_getname,
|
||||
.create = replay_buffer_create,
|
||||
.destroy = replay_buffer_destroy,
|
||||
.start = replay_buffer_start,
|
||||
.stop = ffmpeg_mux_stop,
|
||||
.encoded_packet = replay_buffer_data,
|
||||
.get_defaults = replay_buffer_defaults
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <obs-avc.h>
|
||||
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
#include "obs-ffmpeg-formats.h"
|
||||
|
|
@ -223,11 +224,13 @@ static bool nvenc_update(void *data, obs_data_t *settings)
|
|||
"\twidth: %d\n"
|
||||
"\theight: %d\n"
|
||||
"\t2-pass: %s\n"
|
||||
"\tb-frames: %d\n"
|
||||
"\tGPU: %d\n",
|
||||
rc, bitrate, cqp, enc->context->gop_size,
|
||||
preset, profile, level,
|
||||
enc->context->width, enc->context->height,
|
||||
twopass ? "true" : "false",
|
||||
enc->context->max_b_frames,
|
||||
gpu);
|
||||
|
||||
return nvenc_init_codec(enc);
|
||||
|
|
@ -269,7 +272,9 @@ static void *nvenc_create(obs_data_t *settings, obs_encoder_t *encoder)
|
|||
|
||||
enc = bzalloc(sizeof(*enc));
|
||||
enc->encoder = encoder;
|
||||
enc->nvenc = avcodec_find_encoder_by_name("nvenc_h264");
|
||||
enc->nvenc = avcodec_find_encoder_by_name("h264_nvenc");
|
||||
if (!enc->nvenc)
|
||||
enc->nvenc = avcodec_find_encoder_by_name("nvenc_h264");
|
||||
enc->first_packet = true;
|
||||
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
|
|
@ -296,8 +301,10 @@ fail:
|
|||
}
|
||||
|
||||
static inline void copy_data(AVPicture *pic, const struct encoder_frame *frame,
|
||||
int height)
|
||||
int height, enum AVPixelFormat format)
|
||||
{
|
||||
int h_chroma_shift, v_chroma_shift;
|
||||
av_pix_fmt_get_chroma_sub_sample(format, &h_chroma_shift, &v_chroma_shift);
|
||||
for (int plane = 0; plane < MAX_AV_PLANES; plane++) {
|
||||
if (!frame->data[plane])
|
||||
continue;
|
||||
|
|
@ -306,7 +313,7 @@ static inline void copy_data(AVPicture *pic, const struct encoder_frame *frame,
|
|||
int pic_rowsize = pic->linesize[plane];
|
||||
int bytes = frame_rowsize < pic_rowsize ?
|
||||
frame_rowsize : pic_rowsize;
|
||||
int plane_height = plane == 0 ? height : height/2;
|
||||
int plane_height = height >> (plane ? v_chroma_shift : 0);
|
||||
|
||||
for (int y = 0; y < plane_height; y++) {
|
||||
int pos_frame = y * frame_rowsize;
|
||||
|
|
@ -329,7 +336,7 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
|
|||
|
||||
av_init_packet(&av_pkt);
|
||||
|
||||
copy_data(&enc->dst_picture, frame, enc->height);
|
||||
copy_data(&enc->dst_picture, frame, enc->height, enc->context->pix_fmt);
|
||||
|
||||
enc->vframe->pts = frame->pts;
|
||||
ret = avcodec_encode_video2(enc->context, &av_pkt, enc->vframe,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <util/platform.h>
|
||||
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ struct ffmpeg_cfg {
|
|||
const char *format_name;
|
||||
const char *format_mime_type;
|
||||
const char *muxer_settings;
|
||||
int gop_size;
|
||||
int video_bitrate;
|
||||
int audio_bitrate;
|
||||
const char *video_encoder;
|
||||
|
|
@ -129,10 +131,12 @@ static bool new_stream(struct ffmpeg_data *data, AVStream **stream,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void parse_params(AVCodecContext *context, char **opts)
|
||||
static bool parse_params(AVCodecContext *context, char **opts)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (!context || !context->priv_data)
|
||||
return;
|
||||
return true;
|
||||
|
||||
while (*opts) {
|
||||
char *opt = *opts;
|
||||
|
|
@ -145,11 +149,16 @@ static void parse_params(AVCodecContext *context, char **opts)
|
|||
*assign = 0;
|
||||
value = assign+1;
|
||||
|
||||
av_opt_set(context->priv_data, name, value, 0);
|
||||
if (av_opt_set(context->priv_data, name, value, 0)) {
|
||||
blog(LOG_WARNING, "Failed to set %s=%s", name, value);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
opts++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool open_video_codec(struct ffmpeg_data *data)
|
||||
|
|
@ -162,7 +171,9 @@ static bool open_video_codec(struct ffmpeg_data *data)
|
|||
av_opt_set(context->priv_data, "preset", "veryfast", 0);
|
||||
|
||||
if (opts) {
|
||||
parse_params(context, opts);
|
||||
// libav requires x264 parameters in a special format which may be non-obvious
|
||||
if (!parse_params(context, opts) && strcmp(data->vcodec->name, "libx264") == 0)
|
||||
blog(LOG_WARNING, "If you're trying to set x264 parameters, use x264-params=name=value:name=value");
|
||||
strlist_free(opts);
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +249,7 @@ static bool create_video_stream(struct ffmpeg_data *data)
|
|||
context->width = data->config.scale_width;
|
||||
context->height = data->config.scale_height;
|
||||
context->time_base = (AVRational){ ovi.fps_den, ovi.fps_num };
|
||||
context->gop_size = 120;
|
||||
context->gop_size = data->config.gop_size;
|
||||
context->pix_fmt = closest_format;
|
||||
context->colorspace = data->config.color_space;
|
||||
context->color_range = data->config.color_range;
|
||||
|
|
@ -266,7 +277,7 @@ static bool create_video_stream(struct ffmpeg_data *data)
|
|||
static bool open_audio_codec(struct ffmpeg_data *data)
|
||||
{
|
||||
AVCodecContext *context = data->audio->codec;
|
||||
char **opts = strlist_split(data->config.video_settings, ' ', false);
|
||||
char **opts = strlist_split(data->config.audio_settings, ' ', false);
|
||||
int ret;
|
||||
|
||||
if (opts) {
|
||||
|
|
@ -620,8 +631,10 @@ static void ffmpeg_output_destroy(void *data)
|
|||
}
|
||||
|
||||
static inline void copy_data(AVPicture *pic, const struct video_data *frame,
|
||||
int height)
|
||||
int height, enum AVPixelFormat format)
|
||||
{
|
||||
int h_chroma_shift, v_chroma_shift;
|
||||
av_pix_fmt_get_chroma_sub_sample(format, &h_chroma_shift, &v_chroma_shift);
|
||||
for (int plane = 0; plane < MAX_AV_PLANES; plane++) {
|
||||
if (!frame->data[plane])
|
||||
continue;
|
||||
|
|
@ -630,7 +643,7 @@ static inline void copy_data(AVPicture *pic, const struct video_data *frame,
|
|||
int pic_rowsize = pic->linesize[plane];
|
||||
int bytes = frame_rowsize < pic_rowsize ?
|
||||
frame_rowsize : pic_rowsize;
|
||||
int plane_height = plane == 0 ? height : height/2;
|
||||
int plane_height = height >> (plane ? v_chroma_shift : 0);
|
||||
|
||||
for (int y = 0; y < plane_height; y++) {
|
||||
int pos_frame = y * frame_rowsize;
|
||||
|
|
@ -669,7 +682,7 @@ static void receive_video(void *param, struct video_data *frame)
|
|||
0, data->config.height, data->dst_picture.data,
|
||||
data->dst_picture.linesize);
|
||||
else
|
||||
copy_data(&data->dst_picture, frame, context->height);
|
||||
copy_data(&data->dst_picture, frame, context->height, context->pix_fmt);
|
||||
|
||||
if (data->output->flags & AVFMT_RAWPICTURE) {
|
||||
packet.flags |= AV_PKT_FLAG_KEY;
|
||||
|
|
@ -939,6 +952,9 @@ static bool try_connect(struct ffmpeg_output *output)
|
|||
int ret;
|
||||
|
||||
settings = obs_output_get_settings(output->output);
|
||||
|
||||
obs_data_set_default_int(settings, "gop_size", 120);
|
||||
|
||||
config.url = obs_data_get_string(settings, "url");
|
||||
config.format_name = get_string_or_null(settings, "format_name");
|
||||
config.format_mime_type = get_string_or_null(settings,
|
||||
|
|
@ -946,6 +962,7 @@ static bool try_connect(struct ffmpeg_output *output)
|
|||
config.muxer_settings = obs_data_get_string(settings, "muxer_settings");
|
||||
config.video_bitrate = (int)obs_data_get_int(settings, "video_bitrate");
|
||||
config.audio_bitrate = (int)obs_data_get_int(settings, "audio_bitrate");
|
||||
config.gop_size = (int)obs_data_get_int(settings, "gop_size");
|
||||
config.video_encoder = get_string_or_null(settings, "video_encoder");
|
||||
config.video_encoder_id = (int)obs_data_get_int(settings,
|
||||
"video_encoder_id");
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ static void ffmpeg_source_defaults(obs_data_t *settings)
|
|||
obs_data_set_default_bool(settings, "clear_on_media_end", true);
|
||||
obs_data_set_default_bool(settings, "restart_on_activate", true);
|
||||
obs_data_set_default_bool(settings, "force_scale", true);
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
#if defined(_WIN32)
|
||||
obs_data_set_default_bool(settings, "hw_decode", true);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ OBS_MODULE_USE_DEFAULT_LOCALE("obs-ffmpeg", "en-US")
|
|||
extern struct obs_source_info ffmpeg_source;
|
||||
extern struct obs_output_info ffmpeg_output;
|
||||
extern struct obs_output_info ffmpeg_muxer;
|
||||
extern struct obs_output_info replay_buffer;
|
||||
extern struct obs_encoder_info aac_encoder_info;
|
||||
extern struct obs_encoder_info nvenc_encoder_info;
|
||||
|
||||
|
|
@ -145,6 +146,7 @@ bool obs_module_load(void)
|
|||
obs_register_source(&ffmpeg_source);
|
||||
obs_register_output(&ffmpeg_output);
|
||||
obs_register_output(&ffmpeg_muxer);
|
||||
obs_register_output(&replay_buffer);
|
||||
obs_register_encoder(&aac_encoder_info);
|
||||
if (nvenc_supported()) {
|
||||
blog(LOG_INFO, "NVENC supported");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue