Конвертиране на видео до webm, ogv, mp4, mkv – Ned Video Converter

Ned video converter - ogv, webm, mp4
Беше ми необходима проста програма за конвертиране на видео до webm и ogg video (ogv), която да ми позволява пълен контрол на изходния файл. Тъй като не намерих такава безплатна, освен конзолния ffmpeg, реших да спретна едно GUI за ffmpeg с просто кодиране в AutoIt. Чудих се за името на програмата и реших да не се правя на оригинален, затова е Ned video converter.
Програмата в момента конвертира до webm, avi, ogv, mp4, flv и mkv. Но позволява да се стартира кодиране до всякакъв формат, ако познавате инструментите на ffmpeg. Стартирането на процеса взима стринга от полето Command и така могат ръчно да се променят всички параметри. Например можем да зададем ръчно команда за конвертиране на видео до mp3-файл, като в полето Command въведем следния тринг:

ffmpeg -i <input> -c:a libmp3lame -b:a 256k -vn -f mp3 some_audio_file.mp3

Ned video converter - mp3
Разбира се ръчните настройки са само опционални, спокойно могат да се ползват вградените скромни опции на GUI-то.
Важно е да се отбележи, че при ресайзване на видео по широчина, тогава височината се променя в съотношение, за това зададената височина трябва да е кратна на 2. Това е причината понякога ресайването да не работи. Просто се въвежда нова стойност на широчината, увеличена или намалена с +1 (примерно 600 не работи, тогава се пробва с 601, 602 и т.н.) и се натиска бутона Generate Command.
Ако файловете се получават големи или с недобро качество е добре да се попрочете документацията на ffmpeg. Параметрите за конвертиране могат да се променят и от външния ini-файл, така че да паснат на конкретните нужди.
Прилагам и сорса, който е доволно прост. Отделил съм GUI-частта и фукциите от основния файл, за да има по-добра четимост.
При конжертиране на avi и mkv (matroska) съм задал да се използва параметъра -crf за контрол на качеството. По принцип за запазване на качеството, каквото е във входния файла, параметъра се сетва на -crf 23. За по-малък файл и по-лошо качество може да се остави на -crf 25 или повече. За по-добро качество на картината може да се пробва с -crf 19.
Сорса е абсолютно свободен за ползване, променяне, споделяне.
Изтегляне за 32 и 64bit Windows:
Ned_video_converter-32bit-0.02.zip
Ned_video_converter-64bit-0.02.zip
Ако има проблеми с програмката, моля да ги споделите в коментарите.
По-долу може да се види кратко видео с примерно конвертиране до webm и mp4 формати. Видеото е конвертирано до тези формати, за да мога да го вградя в тази страница. Видеото, което конвертирам е свален от YouTube клип Camila Cabello – Havana ft. Young Thug.

Bootstrap 3 – custom menu, fixed bottom, header, back to top

В програмирането има едно правило, което перефразирано гласи да не търсиш топлата вода всеки път. За това качвам няколко базови кода за Bootstrap 3, които съм писал или копирал и променял. Помогнал съм си леко с Less за някои стилове.

Custom menu
Нищо ново. Добавено е само малко CSS-кодиране на менюто, което се предлага стандартно с Bootstrap.

Bootstrap 3- custom menu

Bootstrap 3- custom menu

Демо

Header
Напаснал съм отделните слоеве с помощта на Boostrap стиловете col-*-push и col-*-pull, така че да има приличен респонзив.

Bootstrap 3- header

Bootstrap 3- header

Bootstrap 3- header

Демо

Fixed bottom
Фиксиран фуутер за мобилни устройства – особено полезно при писане на мобилно приложение, базирано на HTML.

Bootstrap 3- fixed bottom

Bootstrap 3- fixed bottom

Демо

Back to top бутон
Клиентите често искат подобна опция. Кода е няколко реда и има и малко JavaScript, освен CSS-а.

Bootstrap 3- back to top

Демо

Допълнително в архива съм добавил и Bootstrap 3 – login form.

Изтегляне на кода: header_menu_fixed-bottom_back-to-top_login-form.zip

===============
Добавям и още 2 вертикални менюта

Bootstrap 3 – Drop Down menu – only CSS
Bootstrap 3 - CSS Drop Down menu - CSS_only
Демо
Изтегляне

Bootstrap 3 – Drop Down menu – CSS and JavaScript
Bootstrap 3 - CSS Drop Down menu - CSS and JS
Демо
Изтегляне

Bootstrap 3 – Login form

Bootstrap 3 - Login Form
От известно време се каня да променя логин формата за админ панела на проектите, които правя. Направих една форма, която не знам дали ще ползвам, но ще ми е полезна като отправна точка. За да си помогна за стиловете използвах Less (език за стилови множества или CSS) и GUI-то SimpLESS – портабъл е и работи доста леко за разлика от други подобни.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 		MIXINS
//  ==========================================
.rounded-corners (@radius1: 5px, @radius2: 5px, @radius3: 5px, @radius4: 5px) { 
	-webkit-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-moz-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-ms-border-radius: @radius1 @radius2 @radius3 @radius4; 
	-o-border-radius: @radius1 @radius2 @radius3 @radius4; 
	border-radius: @radius1 @radius2 @radius3 @radius4; 
}
 
.drop-shadow (@x: 0, @y: 1px, @blur: 2px, @spread: 0, @alpha: 0.25) {
	-webkit-box-shadow:	@x @y @blur @spread rgba(0, 0, 0, @alpha);
	-moz-box-shadow:	@x @y @blur @spread rgba(0, 0, 0, @alpha);
	box-shadow:		@x @y @blur @spread rgba(0, 0, 0, @alpha);
}
 
.gradient (@startColor: #eee, @endColor: white) {
	background-color: @startColor;
	background: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor));
	background: -webkit-linear-gradient(top, @startColor, @endColor);
	background: -moz-linear-gradient(top, @startColor, @endColor);
	background: -ms-linear-gradient(top, @startColor, @endColor);
	background: -o-linear-gradient(top, @startColor, @endColor);
}
 
 
 
// 		Colors
//  ==========================================
@silver_light: #edf1f2;
@silver_white: #f7f8fa;
@silver_dark: #eef7fc;
@silver_border: #c3d5d9;
@grey: #8f8f8f;
@blue_dark: #76ccea;
@blue_light: #badff2;
 
 
// 		Styles
//  ==========================================
body {
	background-color: @silver_light;
}
 
.container.lf{
	width: 322px;
	color: @grey;
	a {color: @grey;}
 
		.logf {
			margin-top: 50px;
			.rounded-corners(5px, 5px, 5px, 5px);
			.drop-shadow(0px, 0px, 6px, 2px, 0.05);
		}
 
		.lfhead, .lfbody, .lffooter{
			border: 1px solid @silver_border;
			background-color: @silver_white;
			min-height: 20px;
			// line-height: 15px;
		}
 
		.lfhead {
			border-bottom: 0;
			.rounded-corners(5px, 5px, 0, 0);
		}
 
		.lfbody {
			border-top: 0;
			border-bottom: 0;
 
			.input-group-addon {
				color: @grey;
			}
			 .form-control:focus {
			 	.drop-shadow(0px, 0px, 6px, 2px, 0.05);
			 	border-color: @blue_dark;
			 }
		}
 
		.lffooter {
			background-color: @silver_dark;
			.rounded-corners(0, 0, 5px, 5px);
			padding-top: 16px;
 
			.text-left {
				padding-top: 8px;
			}
 
			label {
				font-weight: normal;
				color: @grey;
			}
 
			input[type='button'], input[type='reset'], input[type='submit'] {
				.rounded-corners(18px, 18px, 18px, 18px);
				border-color: @blue_dark;
				.gradient(@blue_light, @blue_dark);
				font-weight: bold;
				.drop-shadow(0px, 1px, 2px, 1px, 0.10);
				text-shadow: 1px 1px @blue_dark;
 
				&:hover {
					.gradient(@blue_dark, @blue_light);
				}
			}
		}
 
	.lflinks {
		padding-top: 8px;
	}
 
}

HTML кода:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div class="container lf">
   <div class="row logf text-center">
      <form action="" method="post" >
         <div class="col-xs-12 lfhead">
         </div>
         <div class="col-xs-12 lfbody">
            <div class="form-group">
               <div class="input-group">
                  <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                  <input id="email" type="email" class="form-control" name="email" value="" tabindex="1" placeholder="Email Address">
               </div>
            </div>
            <div class="form-group">
               <div class="input-group">
                  <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                  <input id="password" type="password" class="form-control" name="password" value="" tabindex="2" placeholder="Password">                    
               </div>
            </div>
         </div>
         <div class="col-xs-12 lffooter">
            <div class="col-xs-6">
               <div class="form-group text-left">
                  <input type="checkbox" tabindex="3" class="" name="remember" id="remember">
                  <label for="remember"> Remember Me</label>
               </div>
            </div>
            <div class="col-xs-6">
               <div class="form-group text-right">
                  <input type="submit" name="login-submit" tabindex="4" class="btn btn-primary" value="Login">
               </div>
            </div>
         </div>
      </form>
   </div>
   <div class="row lflinks">
      <div class="col-xs-6 text-left"><a href="">Register</a></div>
      <div class="col-xs-6 text-right"><a href="">Forgot password</a></div>
   </div>
</div>

Останалото форматиране си идва от Bootstrap 3.
Демо на страницата: BS3 Login Form
Download: bs3-login_form.zip

Преименуване разширението на множество файлове през конзола

Transmission - Rename added extention
Често ми се налага да преминавам от Linux към Windows и обратно. И под двете операционни системи ползвам Transmission за торент клиент. Настроил съм го под Linux да зарежда торент-файловете от директория на версията за Windows. Проблема е, че в такива случаи Transmission под Linux добавя разширението “*.added” на торент файловете. Ако файловете са десетки, трябва да се помисли за автоматизирано преименуване, за да не се губи време. Прилагам няколко варианта, които вършат работата за премахване на *.added разшиернието:

  • Чист Bash:
    for file in *.added; do mv "$file" "${file%.added}"; done;
  • с командата rename (не съм октрил читава версия за Windows, освен в CygWin):
    rename 's/.added$//' *.added

    Или още по-просто:

    rename .sss .txt *.sss
  • с командата mmv – инструмент за масивно местене на файлове по определени критерии
    Ако го няма във вашата Linux дистрибуция, можете да си го добавите. Примерно за Ubuntu:

    sudo apt-get install mmv

    Ако използвате CygWin под Windows, ще трябва да го инсталирате с инсталатора:
    mmv - rename multiple files
    След като го имаме наличен, можем да разкарваме разширения така:

    mmv '*.added' '#1'

    Ако искаме да преименуваме разширения:

    mmv '*.html' '#1.txt'

В случая не преименувам, а премахвам разширението. Но командите спокойно могат да се ползват за преименуване.
Под Windows използвам конзолата на CygWin – страхотен Unix емулатор за Windows.

Amascrap – amazon price scraper

Amazon price scraper - извличане и проследяване на цени
Amascrap е програма тип “web scraper”, която извлича и логва цени от Amazon.co.uk. Програмата е базирана на PHP, HTML, Javascript (jQuery). Вградил съм Traktor на цените, за да имат някаква проследяемост във времето. Скриптовете могат да се използват и като Web-сайт.

Програмата я написах за мен, защото често ми се налага да пазарувам от Amazon.co.uk. Забелязах, че в сайта доста продукти си сменят цените през няколко дни и има значение, дали ще си купиш нещо с 10 паунда по-ниска цена. Все пак съм си българче :). Traktora позволява да следиш, през колко време някой продукт си сменя цената, което си е идеална статистика. Помогна ми да разбера, че някои продукти имат абсолютно точен цикъл на смяна на цената. Особено добре се вижда преди или след празници.
Не съм писал демон за автоматичен ъпдейт, за това цените трябва да се ъпдейтват ръчно. При много продукти и ъпдейт на всички се получава лаг, който няма как да се избегне. Все пак нямам достъп до базата данни на Амазон, нит ползвам API. Чист и класически Web-скрапер с XPath и cURL под PHP.
За GUI използвах PHP Desktop с MSIE (не ме целете с камъни, просто Chrome вдигна много мегабайтите).

Кратък видео урок, как се работи с програмата:

Програмата с сорс-кода може да се изтегли от тук:
Amascrap v.0.04 – Ъпдейт на 13.06.2016. Оправени са проблеми при сваляне на данните през HTTPS.

Laravel – root dir post-request

Има един досаден бъг в Laravel 4.2. Не иска да обработва post-заявка, насочена към root-адреса. Говоря за това:

1
2
3
Route::post('/',function(){
 // ...
});

В такива случаи Laravel сеправи на чук и просто рефрешва страницата.
Открих 2 трики-метода за заобикаляне на бъг-а:
1. Поставя се шпация, ако формата е насочена към текущата страница:

1
{{Form::open(array('url'=>' ','method'=>'post'))}}

2. Пишем точно към кой адрес е насочена формата:

1
{{Form::open(array('url'=>'/index.php','method'=>'post'))}}

Извличане на цветове от картинка с php

Имам една идея за автоматична смяна на цветната схема на Bootstrap-базиран сайт. За целта ми трябва просто извличане на цветовете от картинка с php-скрипт.
За базови цветове създавам проста картинка с квадратчета, като тази:
php extract color from image
За да извлека цветовете от отделните квадратчета използвам php-функцията imagecolorat, която взима цвета на пиксел при зададени кооординати. Координатната система е нулирана в горния ляв ъгъл:
imagecolorat - coordinates
Примерен скрипт в който използвам извличане цвета на пиксел, който се намира горе-долу по средата на всеки правоъгълник:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
// $rgb е array
function rgb2hex($rgb) {
   $hex = "#";
   $hex .= str_pad(dechex($rgb[0]), 2, "0", STR_PAD_LEFT);
   $hex .= str_pad(dechex($rgb[1]), 2, "0", STR_PAD_LEFT);
   $hex .= str_pad(dechex($rgb[2]), 2, "0", STR_PAD_LEFT);
 
   return $hex;
}
 
function get_color_from_pixel($img, $x, $y){
    $im = imagecreatefrompng($img);
    $rgb = imagecolorat($im, $x, $y);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF;
 
    return rgb2hex(array($r, $g, $b));
}
 
// ===================================================
// EXAMPLE
 
$image = "image.png";
$y = 24;
$x_ar = array(33, 103, 177, 244, 315, 385, 454, 526, 593);
 
foreach ($x_ar as $x) {
    $colors[] = get_color_from_pixel($image, $x, $y);
}
print_r($colors);
?>

Резултат:

1
2
3
4
5
6
7
8
9
10
11
12
Array
(
    [0] => #36261c
    [1] => #d5c187
    [2] => #6ecddf
    [3] => #827b3a
    [4] => #2a7d94
    [5] => #9db079
    [6] => #82796d
    [7] => #a7c6da
    [8] => #d54c06
)

Изтегляне на скрипта и картинката: PHP-get_colors_from_image.zip

Проектиране на мебели в Blender 3D – ръководство и видео урок

RENDERED етажерка
Ще се опитам да напиша един урок за просто проектиране, моделиране и програмиране на мебели в Blender. Програмата поддържа езика за програмиране Python, който разполага с безкрайни възможност за създаване и управление на обекти. Ще се постарая да се изразявам максимално простичко и ясно.

Необходими инструменти:
1. Молив
2. Лист хартия
3. Blender 3D – по възможност версия 2.67 или по-нова

Първо да скицираме някакъв по-простичък обект (мебел), който искаме да проектираме. Аз ще създам проста етажерка за окачване на стена. За да улесня максимално процеса, моята етажерка ще е от 4 детайла – 2 еднакви по размер страници + 2 една по размер елемента, които ще са гръб и под. Ето как изглежда моята етажерка:
Схема на етажерка
Сега е време да се сблъскаме с назъбения интерфейс на моделера Blender. Програмата е малко плашеща за нови потребители. Но има голямо комюнити и много уроци, които помагат за овладяването и. Лично аз много харесвам тази програма и използвам предимно базовите и фукнции, които често ми олесняват живота. Нека да започнем със забавата.
Стартираме програмата и натискаме Delete бутона от клавиатурата, за да изтрием куба, който се зарежда под дефолт.
Blender 3D interface
Старайте се да не кликате никъде с мишката, докато не разберете каква е логиката на програмата. Кликовете с мишока са:
– Левия клик поставя 3Д-курсора в точката на кликане
– десния клик върху обект го селектира
– Скролирането в 3D фрейма зумва
– Натиснат среден бутон върти 3Д-фрейма
– среден бутон + задържан Shift мести 3Д-фрейма

Има и доста допълнителни команди, но за тях по-късно.

Сега, докато не сме почнали с експериментите, нека разгледаме координатната система. Намира се долу в ляво:
Blender координатна система
Сега да помислим как да си разположим елементите от нашата етажерка:
Проектиране на етажерка
Важно е да се отбележи, че ще използваме метричната система. Това трябва да му го кажем на Blender, иначе ще прави глупости. За целта правим следните настройки:
Елементите, които трябва да създадем в 3Д са:
– 2 броя страници: 18x240x222mm
– 2 броя плоскости за гръб и под: 850x222x18mm
Тези елементи по-късно ще ги добавим в нашия програмен код. Размерите на всеки елемент могат да се групират в масив. Примерно такъв:
stranici=[0.018, 0.240, 0.222]
gryb=[0.850, 0.222, 0.018]
dyno=[0.850, 0.018, 0.222]

Можем да ги създадем по поне 10 начина, но аз ще ви покажа един много нестандартен подход, който често се оказва най-оптимален и бърз вариант. Ще използвам много просто програмиране на Python. За целта трябва да отворим редактора за въвеждане на Python скриптове. Това също може да стане по много начини, но аз ще използвам предефинираните полета на Blender:
Кликнете бутона Choose Screen layout и изберете Scripting
Blender scripting
Кликнете на бутона +New
Blender new script
!!! Супер важно: Старайте се курсора на мишката винаги да е във фрейма в който работите. Примерно, ако искате да въвеждате текст в текстовия редактор, курсора ви трябва да е в този прозорец (фрейм).
В текстовия редактор пейстнете следния код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import bpy
 
strani=[0.018, 0.240, 0.222]
gryb=[0.850, 0.222, 0.018]
dyno=[0.850, 0.018, 0.222]
 
# създаваме 2-те страници. Те лежат в едно направление
# и можем да използваме цикъл
for x in range(2): # изпълни 2 пъти
    bpy.ops.mesh.primitive_cube_add(radius=1)
    bpy.context.object.dimensions=strani
 
# създаваме гръб
bpy.ops.mesh.primitive_cube_add(radius=1)
bpy.context.object.dimensions=gryb
 
# създаваме пода
bpy.ops.mesh.primitive_cube_add(radius=1)
bpy.context.object.dimensions=dyno

Прозореца със скрипта трябва да изглежда така:
Blender Python script
Командите:

1
2
bpy.ops.mesh.primitive_cube_add
bpy.context.object.dimensions

са въведени в API-интерфейса на Blender. Всяка версия на програмата има документация в която са описани всички команди, които могат да се изпълняват от програмата. Как лесно да разберем коя команда как се ползва ще опиша някой друг път.

Сега трябва да изпълним кода. Натискаме Text->Run Script:
Blender run script
От тук насетне следва местене и рендване в Blender. Действията, които съм извършил в програмата, могат да се видят в по-долното видео:

Vim Editor – Видео урок

Преди доста време бях правил видео за редактора Vim. Направих го за мен, а и заради едни приятели от форум, който посещавах.
Скоро ми се наложи пак да ползвам Vim editor на едно Linux дистро и бях малко като пате в кълчища. За това качвам урока, та другият път да изкарам един бърз курс, ако ми се наложи.

PHP рекурсивно обхождане на дървовидна база данни

Много често се налага да се работи с дървовидни бази данни. С тях могат да се изграждат структури с дъщерни елементи, като например дървовидни менюта за сайт с категория, подкатегория, секция.
Ето едно примерно обхождане на подобна база данни с рекурсия:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
$arr = array(
    // $id, $parent_id, $name
    array(1, 0, "edno"),
    array(2, 0, "dve"),
    array(3, 1, "edno-edno"),
    array(4, 3, "edno-edno-edno"),
    array(5, 1, "edno-dve"),
    array(6, 2, "dve-edno"),
    array(6, 1, "edno-tri")
);
 
function recurse($arr, $pid, $space = '') {
    $output = '<ul>';
 
    foreach ($arr as $key => $ar) {
 
        if ($ar[1] == $pid) {
 
            $output .= "<li>" . $ar[2] . "\n";
            // iztrivane na obhodenite elementi
            $pid_temp = $ar[0];
            unset($arr[$key]);
 
            if ($children = recurse($arr, $pid_temp, $space . '_')) {
                if ($children != '<ul></ul>')
                    $output .= $children;
            }
            $output .= "</li>";
        }
    }
 
    return $output . "</ul>";
}
 
echo recurse($arr, 0, '');

В резултат се получи една чудесна списъчна структура:
Дървовидно обхождане с рекурсия