2018-01-26

Fedora ve Netflix ve hatta başka şeyler

Olay sadece Netflix ile ilgili değil, genel olarak DRM içeriğine sahip tüm siteler için geçerli. Muhtemelen sadece Fedroa ile de ilgili değil, diğer linux dağıtımlarında da aynı şey olabilir. Sorun şu ki ne Netflix videoları, ne de diğer sayısal hak yönetimi diye tercüme edilebilecek DRM nanesine sahip içerik oynatılamıyor. "Netflix video player unavailable" mesajı eşliğinde F7355-1204 hata kodu gösteriliyor. Netflix yardım sayfalarından şu sayfaya ulaştım, ama çok açıklayıcı değil.

Sonra Netflix'in sitesindeki canlı desteğe girip yazdım, hangi codec'i yüklemeliyim diye, oradan da faydalı bir öneri çıkmadı. HTML5 premium codec'ler linux'ta yok falan dediler.

Youtube videolarını falan oynatabiliyordum ama youtube.com/html5 adresine girince farkettim ki aslında H264 eksiğimiz var.


Bu adrese Windows'dan girince şöyle bir ekran çıkıyor.


Demek ki önce H.264 kodeğini bulmak lazım. Derken şu sayfaya denk geldim. Burada deniyor ki, Fedora'da ffmpeg paketi kurulu gelmiyor. Denemek için
# dnf list installed ffmpeg-libs
ile bakmak lazım. Bende yok dedi. Nasıl kuracağız? Yine aynı sayfada Tom G. riken.jp adresinden linkler vermiş. Ben onun yerine rpmfusion repository'sini eklemeyi tercih ettim. Hem free hem de non-free depoları kurmak için şunu kullanmak önerilmiş hem Fedora sitesinde, hem de RPMFusion sitesinde:
# dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
Bundan sonra bir kez
# dnf check-update
ardından da
# dnf install ffmpeg-libs
yaptıktan sonra herşey sorunsuz çalışmaya başladı.

şu sayfada rpmfusion "decent repo" olarak sınıflandırılmış. Ayrıca RpmFusion.org'un şu sayfasında ise kendilerinin bağımsız bir depo olmadıklarını, Fedora'nın depolarının bir uzantısı olarak düşünülmesi gerektiğini yazmışlar.

Linux'ta ağ durumu inceleme

Kullandığımız bilgisayar arka planda ne işler yapıyor? Hangi adresler ile iletişime geçmiş, ne kadar veri trafiği olmuş? Bu gibi soruların cevaplarını bulmak lazım.

İlk iş netstat ile (Fedora'da net-tools paketi ile kurulur) bir durum incelemesi yapmak. Önce etkin bağlantıları inceleyelim:
# netstat -tpn
Burada
 -t : tcp bağlantılarını göster
 -n : isimler yerine sayıları kullan (DNS ters sorgusu yapma)
 -p : ilişkili programları da göster

Dinleyen bağlantıları görmek istersek de:
# netstat -l
kullanılabilir.

Bundan sonraki adımda tcptrack kullanılabilir:
# tcptrack -i wlan0
ki bu komut ile hangi adresi ile ne kadar trafik var görülebilir. Diyelim ki listelenecek bağlantıları belli bir IP adresi ile yapılan bağlantılar ile sınırlamak istiyoruz. Bu durumda
# tcptrack -i wlan0 src or dst 192.168.1.1
yazılarak sadece 192.168.1.1 IP adresinden gelen ve bu adrese giden trafiğin görüntülenmesi sağlanabilir. Nispeten biraz daha görsellik ile bantgenişliğini izlemek için de iftop kullanılabilir:
# iftop -i wlan0
Bu komut terminalde çubuk grafikleri kullanarak hangi IP adresinin ne kadar bantgenişliği kullandığını gösterebilir. Her satır için tablonun sağında 3 sütun yer alır. Bu sütunlar soldan sağa 4, 10 ve 40 saniyelik aralıklardaki toplam trafiği gösterir. Her bağlantı için üstte (sağa doğru ==> ok ile) giden trafik miktarı, altta (sola doğru <== ok ile) gelen trafik miktari gösterilir. Ekranın en altında ise toplam giden gelen ve genel toplam bilgileri yer alır.

Diyelim ki bu yetmedi. Belli bir IP adresi ile gerçekleşen paketlerin içini görmek istiyoruz. Bu durumda da tcpdump [1] kullanılabilir (kurmak için dnf install tcpdump):
# tcpdump -i wlan0 src 192.168.1.1

# tcpdump -i wlan0 udp and host 192.168.1.5

# tcpdump -i wlan0 src port 1025

# tcpdump -i wlan0 icmp 

gibi komutlarla ile gelen trafik, veya src'yi dst ile değiştirerek giden trafik yakalanabilir.

2019-08-26 Ek: Dışarıya doğru yapılan tüm bağlantıları görmek için

ss -tp state establishd

Bu komut ile çok fazla sayıda satır çıkabilir. Aralarından sadece 443 portunu kullananları görmek için

ss -tp state established dst :443 

hem 443 hem de 80 numaralı portları görmek için

ss -tp state established '( dport = :80 or dport = :443 )' 

Bir IP adresine yapılan bağlantı hangi süreç tarafından yapılmış görmek için alternatif olarak ss komutu kullanılabilir. Örneğin

# ss -rep dst 104.199.64.98
Netid  State  Recv-Q  Send-Q   Local Address:Port                   Peer Address:Port  
tcp    ESTAB  0       0        ozm-fed:59624    98.64.199.104.bc.googleusercontent.com:tripe   users:(("spotify",pid=4593,fd=116)) uid:1000 ino:82443 sk:317 <->
Burada kırmızı ile işaretlenen pid bu IP adresine bağlanan sürecin kimliği. Bu kimlik ile süreci bulmak için
$ ps -p 4593
  PID TTY          TIME CMD
 4593 tty2     00:00:55 spotify

Sonucuna erişebiliriz.

---

[1] https://danielmiessler.com/study/tcpdump/#source-destination

Reklam engelleme kuralları

Reklamlar, aslında web'deki ücretsiz içeriğin çarklarını döndüren itici güç. Bu sebeple sade bir reklamın kimseye zararı dokunmaz. Ama internetteki egemen güçlerin ellerindeki çok değerli ve hasass verileri reklam amaçlı kullanmalarının ardından ortada bir dengesizlik oluştu. Hiç farketmeden bizi bizden daha iyi tanıyan internetin "büyük abileri" tarayıcımızın kenarında bizim geçen sene aldığımız ayakkabının benzeri ayakkabı reklamlarını döndürmeye, başka bir sitede sepete eklediğimiz ama henüz satın almasını tamamlamadığımız başka ürünlerin hatırlatmalarını göstermeye başladı. Bu aslında, reklam veren ile hedef kitle arasındaki dengenin bozulduğuna dair bir işaret, sanal dünyanın dönüm noktalarından birisiydi.

Derken reklam engelleyici eklentiler popüler olmaya başladı. Bir haber sitesine girdiğimizde ilgilendiğimiz haberden önce internet operatörümüzün gözümüze soka soka tam sayfa verdiği ilanı en az 10 saniye görmek zorunda bırakılmamız, tatil ve otel bilgileri sunan web sitesinin günde 50 kere görmek zorunda kaldığımız aynı reklamı bizi bu eklentileri kurmaya itti. Sonuçta da şu anda basit bir blog'a bile girsek blog sahibi "bu sayfayı döndürebilmem için reklam almam gerekiyor, lütfen reklam engelleyicinizi kapatır mısınız" türünde mesajlar görüntülemeye başladı.

Ben bu noktada kullanıcıların haklı olduğunu düşünüyorum. Bizi kukla gibi kullanarak ürettikleri her ürünü satabileceklerini düşünerek ilk kurşunu tüketicinin karşısında yer alan konsorsiyum sıktı. Bu durumda tüketicinin de kendini korumaya hakkı var.

Gelelim işin teknik tarafında. Uzun yıllardır AdBlockPlus (ABP) kullandım. Ama git gide surf yapmanın zorlaştığını düşündüğüm bir anda farkettim ki aslında internette gezinmemi zorlaştıran o masum eklentiymiş. Aşırı işlemci ve bellek tüketen bu illetten kurtuldum. Şu anda uBlock Origin kullanıyorum.

Temelde kurallar aynı. ABP veya uBlock için oluşturulmuş genel listeler var. Ama ben daha çok özel birkaç kural yazmak ile ilgileniyorum. Bu konuyla ilgili aşağıdaki tabloyu hazırladım.


KuralEngelleyeceğiEngellenmeyecek
reklamiçinde reklam geçen tüm adresler
swf|http://www.adres.com/reklam.swfhttp://adres.com/swf/icerik.htm
||adres.comhttp://adres.com, https://adres.com, http://tr.adres.com
||adres.com^htttp://adres.com, https://www.adres.com:8080http://adres.com.tr
##.reklam<div class="reklam">, <p class="reklam">
###reklam<div id="reklam">, <table id="reklam">
##reklam<reklam>
##table[width="80%"]<table width="80%"><table>
~https://adres.com/reklam
https://adres.com/reklam
##div[title^="rek"]<div title="reklam">, <div title="reklamlar"><div title="renkli">
##div[title$="lam"]<div title="reklam">, <div title="toplam"><div title="reklamlar">
/^https?://192.168.1.*/192.168.1.0/24 IP bloğu [bkz reddit]
192.168.2.0/24

Ek 2022-07-04:

Bütün bu kurallara ek olarak, kuralın başındaki @@ operatörü, engellemeyi kaldırır. Örneğin

||adres.com

ile adres.com alan adındaki tüm içeriği engellemişken

@@||adres.com/script

sadece adres.com/script'i engellemeden hariç tutar.

2018-01-04

Fedora'da rpm komutu

Bilindiği gibi Fedora, paket yönetiminde RPM (RedHat Package Manager) formatını kullanıyor. Paket yönetiminde dnf gibi çevrim içi ve bağımlılık denetimi yapmadan tekil paketlerin kurulumu ve rpm formatında paket yaratmak için rpm adında bir araç da sunuluyor. Bu aracın kullanımı ile ilgili birkaç anahtara göz atalım.

Diyelim ki elimizde Firefox'un firefox-57.0.1-1.fc26.x86_64.rpm paketi var. Bunu kurmak istiyoruz. Kullanmamız gereken komut
rpm -i firefox-57.0.1-1.fc26.x86_64.rpm
olacak. Ayrıntılı çıktı için -v (verbose) ve paketin açılışı ile ilgili ek bilgiler için -h (hash marks) anahtarları da kullanılabilir. Kurulum aşamasına geçmeden önce paketin imzasının geçerliliğini doğrulamak için -checksig anahtarı kullanılabilir.
rpm -checksig firefox-57.0.1-1.fc26.x86_64.rpm
Bu yöntem dnf gibi çevrim içi paketin bağımlılıklarını kontrol edip yüklemeyecektir. Bunun için kurulu paketin bağımlılıklarını kontrol etmek istersek yapmamız gereken
rpm -qpR firefox-57.0.1-1.fc26.x86_64.rpm
Burada -q (query) paketi sorgulamak için,  -p (capabilities provided) paketin sunduğu özellikleri listelemek için, -R (capabilities this package depends on) paketin bağımlı olduğu özellikleri sorgulamak için eklendi.

Bir paket, bağımlı olduğu diğer paketler kurulmadan kurulamaz. Ama rpm'in -nodeps anahtarını kullanarak paketi bağımlılıklarını görmezden gelerek kurmaya zorlayabiliriz. Bu durumda kurduğumuz paket, bağımlılıklarını sağlamadan yine çalışmayacaktır. Ama bağımlılıkları sonradan sağlamayı isteyerek kurmak istenmesi durumunda gerekebilir.
rpm -ivh -nodeps firefox-57.0.1-1.fc26.x86_64.rpm
Bir paketin sisteminizde kurulu olup olmadığını sorgulamak için
rpm -q firefox
kullanılabilir. Bunun sonucunda paket kurulu değilse
package firefox is not installed
çıktısı verir. Kurulu ise uyan paketin tam adını yazar:
firefox-57.0.1-1.fc26.x86_64.rpm
gibi. Görüldüğü gibi burada paketin sürüm ve platform bilgisi içermeyen adını kullanarak da sorgu yapabiliyoruz. Tab tuşuyla tamamlama da kullanılabiliyor.

"Kurulu" bir paketin tüm içeriğini sorgulamak için ise -ql kullanılabilir.
rpm -ql firefox-57.0.1-1.fc26.x86_64.rpm
Sistemdeki kurulu tüm paketleri sorgulamak için
rpm -qa
Bir paketi yükseltmek (güncellemek) için -U ile birlikte -v (verbose) ve -h (hash marks) anahtarları kullanılabilir:
rpm -Uvh firefox-57.0.1-1.fc26.x86_64.rpm
Bu komut ile güncellenene sürüm ile eski sürüm aynı anda sistemde kalabilir, yenisi ile ilgili bir sorun olursa eskisi kullanılabilir denmiş, denemedim.

Bir paketi kaldırmak için -e (erase) anahtarı kullanılabilir. Paketi bağımlılıklarına bakmaksızın kaldırmak için kaldırmak için ise yine -nodeps anahtarı kullanılabilir.
rpm -evv -nodeps firefox
Sistemde bir sürü dosya var. Bu dosyaların bir tanesinin hangi paketle geldiğini merak ediyoruz. Bunu bulmak için kullanacağımız komut şu:
rpm -qf /usr/lib/libdl.so.2
Sonuç olarak tüm paket ismini döner, aşağıdaki gibi:
glibc-2.25-12.fc26.i686
Kurulu bir paket hakkında ayrıntılı bilgi sorgusu için -qi (query info) kullanılır. Örneğin yukarıda çıkan glibc paketini sorgulayalım.

$ rpm -qi qlibc
Name        : glibc
Version     : 2.25
Release     : 12.fc26
Architecture: x86_64
Install Date: Wed 15 Nov 2017 01:09:18 AM EST
Group       : System Environment/Libraries
Size        : 13990324
License     : LGPLv2+ and LGPLv2+ with exceptions and GPLv2+
Signature   : RSA/SHA256, Wed 11 Oct 2017 12:22:14 PM EDT, Key ID 812a6b4b64dab85d
Source RPM  : glibc-2.25-12.fc26.src.rpm
Build Date  : Wed 11 Oct 2017 09:05:41 AM EDT
Build Host  : buildhw-06.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://www.gnu.org/software/glibc/
Summary     : The GNU libc libraries
Description :
The glibc package contains standard libraries which are used by
multiple programs on the system. In order to save disk space and
memory, as well as to make upgrading easier, common system code is
kept in one place and shared between programs. This particular package
contains the most important sets of shared libraries: the standard C
library and the standard math library. Without these two libraries, a
Linux system will not function.


Bu kurulu bir paket için sorguydu. Kurulmamış, elimizde rpm uzantılı kurulum dosyası olan bir paket için ayrıntlı bilgi sorgulaması için ise -qip (query info package) kullanılır.

$ rpm -qip firefox-57.0.1-1.fc26.x86_64.rpm
Name        : firefox
Version     : 57.0.1
Release     : 1.fc26
Architecture: x86_64
Install Date: (not installed)
Group       : Unspecified
Size        : 208973671
License     : MPLv1.1 or GPLv2+ or LGPLv2+
Signature   : RSA/SHA256, Fri 01 Dec 2017 02:45:19 AM EST, Key ID 812a6b4b64dab85d
Source RPM  : firefox-57.0.1-1.fc26.src.rpm
Build Date  : Thu 30 Nov 2017 07:54:13 AM EST
Build Host  : buildvm-16.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : https://www.mozilla.org/firefox/
Summary     : Mozilla Firefox Web browser
Description :
Mozilla Firefox is an open-source web browser, designed for standards
compliance, performance and portability.


Bir de bazen bozulan rpm veritabanını tekrar oluşturma bilgisi verilmiş, yazının sonunda görülen referans belgede. O da şöyle:
# cd /var/lib
# rm __db*
# rpm --rebuilddb
# rpmdb_verify Packages

2025-04-20 Ek: Bir paketin bağımlılıklarını görmek için

tracker miners paketinin ihtiyaç duyduğu paketler:

rpm -q --whatprovides tracker-miners

tracker-miners paketine ihtiyaç duyan paketler:

rpm -q --whatrequires tracker-miners 

---
[1] https://lintut.com/how-to-use-rpm-command-on-linux/

2017-12-28

Powershell ile belirtilen zamanda bir komut çalıştırma

Şöyle bir ihtiyacım var; sunucularımdan birinin bu gece yarısından sonra saat 03:00'te tekrar başlamasını istiyorum. Bunu zamanlanmış görevlerle yapabilirim. Ama powershell ile yapmak istiyorum. Açık bir powershell penceresi bırakarak şu komutları yazarsam bu mümkün:

Start-Sleep -Seconds (New-Timespan -End '2099-12-29 03:00').TotalSeconds; Restart-Computer

Burada Start-Sleep cmdlet'i belli bir süre beklemeyi sağlayacak. Ne kadar bekleyeceğini New-Timespan cmdlet'i ona söyleyecek. New-Timespan cmdlet'i şu andan itibaren 29.12.2017 saat 03:00'e kadar ne kadar zaman beklemesi gerektiğini hesaplayacak. TotalSeconds ile de bu süreyi saniye cinsinden Start-Sleep cmdlet'ine verecek [1]. Bu kadar süre beklendikten sonra da Restart-Computer cmdlet'i ile sistemin tekrar başlaması sağlanacak.

Ancak bu komut dizisi, kopyala ve yapıştır amaçları için biraz tehlikeli. Yukarıdaki komutu kopyalayıp doğrudan powershell penceresine yapıştırıp orada tarih ve saati düzenleyeyim dersek doğrudan işletebilir. Daha önce orada yıl olarak 2099 yerine 2017 yazdığı ve o tarih de geçmişte kaldığı için makineyi doğrudan yeniden başlatmaya geçiyordu. Bunun için oraya yıl olarak uzak bir tarih girdim. Bir metin düzenleyicide (ör. Notepad) tarihi değiştirmeyi seçebilir, ya da kabaca kaç saat ve dakika sonra başlatılacağını hesaplayarak Start-Sleep cmdlet'ine bir elle hesaplanmış saniye miktarı verebiliriz. Örneğin 3 saat 45 dakika sonra komut çalıştırmak için

Start-Sleep -Seconds ((3*60+45)*60); Restart-Computer

2024-07-04 ek: Hatta belki de bir zamanlanmış işler (Scheduled Jobs) nesnesi kullanabiliriz. Örneğin bugün 22:30'da çalışacak bir işlem için

$baslat = New-JobTrigger -Once -At 22:30
Register-ScheduledJob -Trigger $baslat -Name "Restart" -ScriptBlock {Restart-Computer -Force}

-Force parametresi olmadan olmadı. 

2024-11-20 ek: Konu sadece kapatma veya yeniden başlatma ise, bunu powershell kullanmadan komut satırı programı shutdown.exe ile de yapabiliriz. Örneğin yeniden başlatmak için

shutdown /r /t 3600 # 3600 saniye, yani 60 dakika sonra çalışacak

Burada 3600, saniye cinsinden gecikme miktarı. Powershell komut satırını kullanıyorsak buraya gecikmeyi hesaplayacak bir ifadeyi parantez içinde girebiliriz. Örneğin 1 saat 15 dk sonra yeniden başlatmak için

shutdown /r /t (75*60) # 75 dakika sonra çalışacak

Yeniden başlatma yerine bir kapatma işlemi yapmayı planlıyorsak, /r anahtarını /s ile değiştirmek gerek:

shutdown /s /t 3600 # 1 saat sonra kapanacak

Shutdown komutuyla verilen bir yeniden başlatma veya kapatma işlemini durdurmak için /a anahtarı (abort) kullanılabilir.

shutdown /a 
--- 

[1] http://www.madwithpowershell.com/2013/08/sleep-until-certain-time-with-powershell.html

2017-12-26

sort komutu

Powershell'deki sort (aslında Sort-Object'in alias'ı) ile ilgilendikten komut satırındaki sort baştan biraz daha yavan gelmişti. Ama yine de çok güçlü. Temel amacı bir metin dosyasındaki verileri sıralamak. Örnek sabit uzunluklu alanlara sahip metin veriler.txt dosyamızda aşağıdaki gibi bir veri olsun:

2014-09-12 Cihan  1993
2017-10-01 Zeynep 1992
2013-05-02 Mutlu  1991


3 sütun veri var. İlk sütun bir tarih alanı. Ama tarihler metin sıralaması yapılabilmesi için yıl-ay-gün şeklinde yazılmış. Aksi takdirde gün-ay-yıl şeklinde olan bir alanda metin sıralaması yapabilmek için tarih veri tipinden anlayan, hatta farklı formatlardaki tarihleri algılayabilen bir algoritma gerekli, ama bu sort ile imkansız. İkinci sütunumuz düz metin tabanlı isimlerden oluşuyor. Üçüncü sütun ise tamsayılardan oluşan yıl bilgisi.

Görüldüğü gibi veriler metin dosyasında sıralanMAmış şekilde yer alıyor. Bu verileri örneğin tarihe göre sıralamak için
sort veriler.txt
demek yeterli. Tarih ilk sütunda yer aldığı için sonuç aşağıdaki gibi olacaktır

2013-05-02 Mutlu  1991
2014-09-12 Cihan  1993
2017-10-01 Zeynep 1992


İkinci sütundaki isimlere göre sıralamak için
sort veriler.txt /+12
komutu işimizi görür. İsimler sütununun ilk karakteri 12'den başladığı için /+12 anahtarı ile sıralamada dikkate alınacak bölümün 12. karakterden sonrası olduğunu belirttik. Burada önemli olan şu; sort aslında sadece isimlere göre sıralamıyor, isim+yıla göre sıralıyor. Önceki örnekte de bu geçerliydi. Sort tarih+isim+yıla göre sıraladı. /+12 anahtarı ile alınan (isim+yıla göre sıralama) sonuç şöyle:

2014-09-12 Cihan  1993
2013-05-02 Mutlu  1991
2017-10-01 Zeynep 1992


Üçüncü sütundaki yıl bilgisine göre sıralamak istersek, 199x'ların 1'i 19. karakterden başladığı için
sort veriler.txt /+19
Burada yıl sütununun sağında başka sütun olmadığı için doğal olarak sıralamaya sadece yıl bilgisi dahil edildi.

2013-05-02 Mutlu  1991
2017-10-01 Zeynep 1992
2014-09-12 Cihan  1993


Sıralama varsayılan olarak küçükten büyüğe (1'den 9'a, a'dan z'ye) yapılır. Sıralamayı ters çevirmek için /R anahtarı kullanılabilir.

sort veriler.txt /+19 /R
sonuç:

2014-09-12 Cihan  1993
2017-10-01 Zeynep 1992
2013-05-02 Mutlu  1991


İlk örnekten beri vurguladığım "sıralamaya dahil edilen alan uzunluğu"nu kısıtlamak için /REC anahtarı kullanılabilir. Örneğin sıralamayı sadece ayın gününe göre yapmak için sıralmaya dahil edilecek veriyi 9'dan başlatıp 2 karakter uzunluğunda tutmalıyız:
sort veriler.txt /+9 /REC 2
Bu şekilde şu sonucu elde ederiz:

2017-10-01 Zeynep 1992
2013-05-02 Mutlu  1991
2014-09-12 Cihan  1993


Bir de bu sıralanmış çıktıyı başka bir dosyaya yazmak istersek /O anahtarını şu şekilde kullanabiliriz:
sort veriler /+9 /REC 2 /O sirali.txt
Eğer bu dosyayı Powershell'de sadece tarihe göre sıralamak (aslında tüm satıra göre) istersek şu olabilir:
PS C:\>Get-Content veriler.txt | Sort-Object

Ama bu verileri isim veya yıla göre sıralamak isteyince bunun şaşırtıcı bir şekilde daha zor olduğunu gördüm. Çünkü PowerShell'in sabit uzunluklu verileri import edecek varsayılan bir yöntem yok.

2026-08-11 Ek: Bir süre sonra bakınca farkettim ki ConvertFrom-String bu işe uygun:

Get-Content veriler.txt | ConvertFrom-String

ile veriler şu şekilde alınabildi:

P1                  P2       P3
--                  --       --
12.09.2014 00:00:00 Cihan  1993
01.10.2017 00:00:00 Zeynep 1992
02.05.2013 00:00:00 Mutlu  1991

Alan adlarının da olmasını istersek ConvertFrom-String'e bir parametre daha ekleyip dosyada alan adları olmasa da bunu yapabiliriz.

Tarih               Isim    Yil
-----               ----    ---
12.09.2014 00:00:00 Cihan  1993
01.10.2017 00:00:00 Zeynep 1992
02.05.2013 00:00:00 Mutlu  1991 
Get-Content veriler.txt | ConvertFrom-String -PropertyNames "Tarih","Isim","Yil"

Sonrasında da istenen alana göre sıralama işlemi yapılabilir:

Get-Content veriler.txt | ConvertFrom-String -PropertyNames "Tarih","Isim","Yil" | Sort-Object -Property Tarih

gibi. Daha "düşük seviyeli (!)" bir yöntem ile satır satır sabit genişlikli bir ayırma şöyle olabilirdi:

Get-Content veriler.txt | % { $_ -replace '(.{10}) (.{6}) (.{4})','$3 $1 $2'}
1993 2014-09-12 Cihan
1992 2017-10-01 Zeynep
1991 2013-05-02 Mutlu 

Görüldüğü gibi sütunların yerini bile değiştirebildim. Hatta belki:

Get-Content veriler.txt | % {
    $a,$tarih,$isim,$yil,$b = ($_ -split '(.{10}) (.{6}) (.{4})')
    [PSCustomObject]@{
        Tarih=$tarih
        Isim=$isim
        Yil=$yil
    }
}

$a ve $b burada boş alanlar. Buna niye ihtiyaç duyduğumu şu yazıda inceledim.

Eğer dosya tipi CSV (virgülle ayrılmış değerler) olsaydı

tarih,isim,yıl
2014-09-12,Cihan,1993
2017-10-01,Zeynep,1992
2013-05-02,Mutlu,1991


bu dosyayı Import-CSV ile import edebilirdik. Dikkat, bu dosyada bir farklılık daha var: sütun başlıkları.

PS C:\> Import-Csv .\veriler.txt
tarih                      isim                          yıl
-----                      ----                          ---
2014-09-12                 Cihan                         1993
2017-10-01                 Zeynep                        1992
2013-05-02                 Mutlu                         1991


Burada boru ( | ) operatörü ile çıkışı doğrudan Sort-Object cmdlet'ine gönderebiliriz (kısaca sort).

PS C:\> Import-Csv .\veriler.txt | sort

Bu varsayılan olarak tarih alanına göre sıralar

tarih                      isim                          yıl
-----                      ----                          ---
2013-05-02                 Mutlu                         1991
2017-10-01                 Zeynep                        1992
2014-09-12                 Cihan                         1993


İstediğimiz alana göre sıralamak için tırnak içinde alan adını yazıp, sıralamayı büyükten küçüğe yapmak için ise -Descending anahtarını kullanabiliriz.

İlle de powershell ve sabit uzunluklu alanlar diyorsak önce metin dosyasını okuyup bir değişkene atmak gerek:

PS C:\> $metin = Get-Content .\veriler.txt
Daha sonra da bu içeriği CSV'ye uygun şekle çevirmek gerek. veriler.txt dosyasında sütunlar arasında birden fazla boşluk olabildiği için doğrudan boşluğu virgülle değiştirmek işe yaramaz. Bunun için önce her sütunun sadece 1 boşluk ile ayrılmasını sağlamak gerek. Yeterli sayıda şu komutu ard arda kullanmak ilk adım:
PS C:\> $metin = $metin -replace "  "," "
yukarıda -replace'ten sonra çift tırnakların arasında 2 boşluk karakteri, ikinci çift tırnakların arasında ise 1 boşluk karakteri var. Sonrasında her boşluğu virgülle değiştirmek gerek:
PS C:\> $metin = $metin -replace " ",","
Daha sonra da bu verilere bir başlık satırı eklemek gerek. Önce bir $csv değişkeni oluşturalım:
PS C:\> $csv =  @() 
Başlık satırını ekleyelim:
PS C:\> $csv += "Tarih,Isim,Yil"
Sonra buna verilerimizi ekleyelim
PS C:\> $csv += $metin
Nihayetinde de bunu ConvertFrom-CSV ile çevirelim
PS C:\> $csv = $csv | ConvertFrom-Csv
Bu noktada $csv değişkenimiz aynen bir CSV dosyasından aktarılmış gibi uygun formatta olacaktır.

Not: Türkçe karakterler (yıl başlığındaki ı harfi) her zamanki gibi sorun. Güzel gözüksün diye  düzelttim.

2017-11-28

ffmpeg kullanımı

Komut satırından video dönüştürme, kırpma ve ses ekleme/çıkartma işlemleri için ideal bir araç. Birkaç kullanıma örnek vermek istiyorum.

En basit örnek olarak avi dosyasını mp4'e dönüştürmeyi deneyelim.
ffmpeg -i input.avi output.mp4
Burada -i anahtarı giriş videosunu gösterir. Çıkış dosyası için bir anahtarı kullanılmaz. Yukarıdaki örnekte ayrıca kodek, bit oranı, kare sayısı vs. gibi parametreleri belirtmedik, çünkü ffmpeg varsayılanları kullanarak dönüşüm yaptı. Eğer varsayılanların haricinde değerler kullanmak istiyorsak şöyle bir komut işimizi görürdü:
ffmpeg -i input.avi -vframes 24 -aspect 4:3 -b:a 128k -b:v 2000k -c:a mp3 -c:v libx264 - output.mp4
Burada kullanılan ve kullanılmayan anahtarlar şöyle:

-frames:v number    çıkışa verilecek -toplam- kare sayısı
-ar rate            kare hızı (Hz değeri, ondalık veya kısaltma)
-s size             kare boyutu (Gen x Yük veya kısaltma)
-aspect oran        resim oranı (4:3, 16:9 or 1.3333, 1.7777)
-bits_per_raw_sample oran  ham örnek için bit oranı
-vn                 videoyu akışını görmezden gel (sil)
-c:v codec          video kodeği

-c:a codec          ses kodeği
-timecode hh:mm:ss[:;.]ff  başlangıç zamanını belirtmek için
-pass n             geçiş sayısı (iteratif, 1'den 3'e)
-filter:v filter    video filtresi ayarlamak için
-b:a bitrate        ses bit oranı
-b:v bitrate        video bit oranı
-dn                 verileri görmezden gel


Videonun içinden bir kısmı kesip çıkartmak için:
ffmpeg -i input.avi -ss 00:01:05 -t 00:00:55 output.avi
Örneğin yukarıdaki komut 1. dakika 5. saniyede başlayıp 55 saniye sürecek (yani tam 2. dakikada bitecek) şekilde parçayı kesip çıkartır. Yukarıdaki komut kesme işleminden sonra avi tipi için varsayılanları kullanarak yeniden kodlama yapar. Yeniden kodlamadan kaydetmek için ses ve video kodekleri anahtarlarına "copy" yazmak gerekir. Örneğin
ffmpeg -i input.avi -ss 00:01:05 -t 00:00:05 -c:v copy -c:a copy output.avi
Bir video dosyasından sadece sesi alıp onu da mp3 formatında kaydetmek için
ffmpeg -i input.avi -vn output.mp3
Elbette yine sesle ilgili şu anahtarları kullanabiliriz:

-frames:a sayı      çıkışa verilecek ses "frame"i sayısı
-aq kalite          ses kalitesi (kodeğe özel)
-ar oran            Hertz cinsinden ses örneği sayısı
-ac kanal           ses kanalı sayısı
-an                 sesi görmezden gel (sil)
-c:a codec          Ses kodeğini belirt (değişiklik yapmadan 'copy')

-b:a oran           ses bit oranı
-vol volume         ses seviyesi (0 en az, 256 en yüksek)
-filter:a filter    ses filtresi

-c:a pcm_s16le      örnek başına 16 bit kodlama, signed, little-endian (tam liste)
-f s16le            ham veri, signed, little-endian 16-bit

Ayrı ayrı dosyalarda bulunan ses ve videoyu birleştirmek için (formata hiç dokunmadan):
ffmpeg -i input_video.mp4 -i input_audio.mp3 -c:v copy -c:a copy output.mp4
Buna göre örneğin elimizde kayıpsız flac dosyası varsa ve bundan 256k 44kHz 2 kanal kodlanmış mp3 yaratmak istiyorsak:
ffmpeg -i input.flac -b:a 256k -ar 44100 -ac 2 output.mp3
Kullanılabilir kodek listesini görmek için
ffmpeg -codecs
 kullanabilirz. Benzer şekilde -formats, -muxers, -demuxers, -encoders, -decoders, -filters anahtarları da mevcut.

Video kalitesini belirtmek için görüntü kodlamasında kullanılacak bit oranını belirtebiliriz:
-b:v 128k
video kodeğinin saniyede 128 kilobit veri üretmesini sağlar. -qscale veya -vbr gibi değişken bit oranlı (kalite bazlı) parametreler de kullanmak mümkün. Ama bunların değerleri kodeğe bağlı.

Bir videonun her karesini resim olarak kaydetmek için
ffmpeg -i input.mp4 resim-%03.jpg

diyebiliriz. Burada %03, 3 haneli, başında sıfırlar bulunan sayıları ifade eder. Yani 000, 001, 002,... 999 dizisi. Eğer 1000 taneden fazla resim varsa ilk çıkarılanların üzerine yazılır. Benzer bir hedef ile animated GIF dosyasının her bir karesini bir resim olarak kaydetmek için

ffmpeg -i animated.gif kare-%03.jpg

işe yarar. Tam tersi durumda resim dizizinden video yapmak için ise

ffmpeg -i resim-%03.jpg output.mp4
kullanılabilir. Burada -f image2 ile format gizli bir şekilde ima ediliyor. Ama ffmpeg çıkış formatlarını akıllı bir şekilde anlayabildiği için bu anahtara gerek kalmıyor. Eğer resimlerin başlangıcı 000 değilse bu durumda örneğin 138'den başlayan resimleri belirtmek için
ffmpeg -start_number 138 -i resim-%03.jpg output.mp4
yazılmalı. Varsayılan olarak saniyede 25 resim gösterilir. Bu oranı değiştirmek için -framerate (veya yeni sürümlerde -r) ile bir kare oranı belirtebiliriz. Bir sunum tarzı video hazırlıyorsak ve her karenin 5 saniye görünmesini istiyorsak yapılacak
ffmpeg -r 1/5 -i resim-%03 output.mp4
şeklinde 1/5 kare oranı seçmeliyiz. Resimlerin arasında silinen bir geçiş olmasını istiyorsak bunu aşağıdaki şekilde yapabiliriz:
ffmpeg -i resim-%03d.jpg -vf zoompan=d=(A+B)/B:fps=1/B,framerate=25:interp_start=0:interp_end=255:scene=100 -c:v mpeg4 -maxrate 5M -q:v 2 output.mp4
Burada A her resmin saniye cinsinden geçişsiz gösterilme süresini, B ise geçişteki silinme etkili gösterilme süresini belirtir.

Saniyede 1 resim çıkartmak için
ffmpeg -i video.webm -vf fps=1 resim-%03d.png
ya da seçilen dakika ve saniyedeki görünen resmi çıkartmak için ise

ffmpeg -i video.webm -ss 00:00:10 -vframes 1 thumbnail.png
kullanılabilir.

Filtreler özellikle çok faydalı olabilir. Örneğin ses için fade-in ve/veya fade-out eklemek için şu şekilde bir kullanım uygun:
ffmpeg -i audio.mp3 -filter:a 'fade=in:0:30,fade=out:9650:30' audio_fade.mp3
Bu şekilde fade-in için 0 ile 30. kareler arasında, fade-out için ise 9650 ile 9580 arasındaki kareler verilmiş.

ffmpeg bazı video filtrelerine de sahip. Örneğin bir videoyu ters çevirmek için reverse filtresi kullanılır:
ffmpeg -i input.mp4 -filter:v reverse output.mp4
Bu işlem, girişteki dosyanın büyüklüğüne göre videoyu tek parçada veya parça parça tersine çevirip sonra bunları ekleyerek nihai videoyu oluşturmasını sağlayabilir.

Ekleme 2020-07-28: Resim dosyaları üzerinde de benzer işlemler yapılabilir. Örneğin bir resmi 640x480'e ölçeklendirmek için

ffmpeg -i resim.jpg -vf "scale=640:480" resim_olcekli.jpg

Ya da resmin içinden x=100 ve y=120 konumundan (resmin sol üst köşesi x=0 ve y=0 olmak üzere) başlayıp x=300 ve y=250'ye kadar olan dikdörtgen alanı kırpmak için (genişlik : 300-100 = 200, yükseklik: 250-120 = 130)

ffmpeg -i resim.jpg -vf "crop=200:130:100:120 resim_kirpilmis.jpg

yazılabilir.

Ekleme 2022-07-13: Ayrıca streaming videoları indirmek için de, eğer m3u8 uzantılı bir dosyamız varsa, şöyle bir komut kullanabiliriz:

ffmpeg -i "http://example.com/video_url.m3u8" -c copy -bsf:a aac_adtstoasc "output.mp4"