Gabungkan semua file ts ke dalam 1 file dengan ffmpeg
@echo off
setlocal
REM Define the directory to search for .ts files
set "directory=."
REM Define the output file
set "inputfile=sorted_ts_files.txt"
REM List all .ts files, sort them, and output to the text file
dir /b "%directory%\*.ts" | sort > "%inputfile%"
REM Notify the user
echo Sorted list of .ts files has been saved to %inputfile%
REM Define the input and output files
set "inputfile=sorted_ts_files.txt"
set "concatfile=concat_list.txt"
set "outputfile=output.ts"
REM Check if the input file exists
if not exist "%inputfile%" (
echo Input file %inputfile% does not exist.
exit /b 1
)
REM Create the concat file for ffmpeg
echo Creating concat file for ffmpeg...
> "%concatfile%" (
for /f "usebackq delims=" %%a in ("%inputfile%") do echo file '%%a'
)
REM Join the video files using ffmpeg
echo Joining video files...
ffmpeg -f concat -safe 0 -i "%concatfile%" -c copy "%outputfile%"
REM Cleanup
del "%concatfile%"
del "%inputfile%"
echo Done. The output file is %outputfile%.
endlocal
This can be done directly from the webinterface. Just go to Plugins -> Plugin Editor -> select the Plugin SyntaxHighlighter Evolved -> add the snippet to the end
//File: Serial.h
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class Serial
{
private:
//Serial comm handler
HANDLE hSerial;
//Connection status
bool connected;
//Get various information about the connection
COMSTAT status;
//Keep track of last error
DWORD errors;
public:
//Initialize Serial communication with the given COM port
Serial(char *portName);
//Close the connection
~Serial();
//Read data in a buffer, if nbChar is greater than the
//maximum number of bytes available, it will return only the
//bytes available. The function return -1 when nothing could
//be read, the number of bytes actually read.
int ReadData(char *buffer, unsigned int nbChar);
//Writes data from a buffer through the Serial connection
//return true on success.
bool WriteData(char *buffer, unsigned int nbChar);
//Check if we are actually connected
bool IsConnected();
};
#endif // SERIALCLASS_H_INCLUDED
//File: Serial.cpp
#include "Serial.h"
Serial::Serial(char *portName)
{
//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
#if _MSC_VER && !__INTEL_COMPILER
const size_t cSize = strlen(portName) + 1;
wchar_t* wc = new wchar_t[cSize];
mbstowcs_s(NULL, wc, cSize, portName, cSize);
this->hSerial = CreateFile(wc,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
#else
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile(portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
#endif
//Check if the connection was successfull
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else
{
//If connected we try to set the comm parameters
DCB dcbSerialParams = {0};
//Try to get the current
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
//If impossible, show an error
printf("failed to get current serial parameters!");
}
else
{
//Define serial connection parameters for the arduino board
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
//Setting the DTR to Control_Enable ensures that the Arduino is properly
//reset upon establishing a connection
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
//Set the parameters and check for their proper application
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
//If everything went fine we're connected
this->connected = true;
//Flush any remaining characters in the buffers
PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
//We wait 2s as the arduino board will be reseting
Sleep(2000);
}
}
}
}
Serial::~Serial()
{
//Check if we are connected before trying to disconnect
if(this->connected)
{
//We're no longer connected
this->connected = false;
//Close the serial handler
CloseHandle(this->hSerial);
}
}
int Serial::ReadData(char *buffer, unsigned int nbChar)
{
//Number of bytes we'll have read
DWORD bytesRead;
//Number of bytes we'll really ask to read
unsigned int toRead;
//Use the ClearCommError function to get status info on the Serial port
ClearCommError(this->hSerial, &this->errors, &this->status);
//Check if there is something to read
if(this->status.cbInQue>0)
{
//If there is we check if there is enough data to read the required number
//of characters, if not we'll read only the available characters to prevent
//locking of the application.
if(this->status.cbInQue>nbChar)
{
toRead = nbChar;
}
else
{
toRead = this->status.cbInQue;
}
//Try to read the require number of chars, and return the number of read bytes on success
if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
{
return bytesRead;
}
}
//If nothing has been read, or that an error was detected return -1
return -1;
}
bool Serial::WriteData(char *buffer, unsigned int nbChar)
{
DWORD bytesSend;
//Try to write the buffer on the Serial port
if(!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
{
//In case it don't work get comm error and return false
ClearCommError(this->hSerial, &this->errors, &this->status);
return false;
}
else
return true;
}
bool Serial::IsConnected()
{
//Simply return the connection status
return this->connected;
}
Berikut contoh koneksi pengiriman data
#include <iostream>
#include "windows.h"
#include "Serial.h"
#include <thread>
#include <chrono>
using namespace std;
void delay(int ms){
std::this_thread::sleep_for (std::chrono::milliseconds(ms));
}
int main(int argc, char** argv) {
char alamatPort[] = "\\\\.\\COM7";
Serial* s = new Serial(alamatPort);
char dataOn[256] = "on1\n"; //"Nyala!";
char dataOff[256] = "off0\n"; //"mati!";
cout<<"isikan angka 1 untuk menyalakan, atau 0 untuk mematikan"<<endl;
int jawab;
do{
cin>>jawab;;
if(jawab==0)
s->WriteData(dataOff, sizeof(dataOff));
if(jawab==1)
s->WriteData(dataOn, sizeof(dataOn));
if(jawab==2)
for(int a=0;a<5;a++){
s->WriteData(dataOn, sizeof(dataOn));
delay(500);
s->WriteData(dataOff, sizeof(dataOff));
delay(500);
}
}while(jawab<3);
return 0;
}
Berikut contoh untuk mengirim dan menerima data
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include "Serial.h" // Library described above
#include <string>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
char alamatPort[] = "\\\\.\\COM7";
Serial* SP = new Serial(alamatPort); // adjust as needed
void* baca(void* data)
{
char incomingData[256] = ""; // don't forget to pre-allocate memory
//printf("%s\n",incomingData);
int dataLength = 256;
int readResult = 0;
while (SP->IsConnected())
{
readResult = SP->ReadData(incomingData, dataLength);
if (readResult > 0) {
printf("%s\n", incomingData);
}
//printf("Bytes read: (-1 means no data available) %i\n",readResult);
//std::string test(incomingData);
//printf("%s",incomingData);
//test = "";
Sleep(500);
}
return NULL;
}
void* tulis(void* data)
{
while (SP->IsConnected())
{
char outgoingData[256] = "";
char keluar[256] = "keluar";
int dataLength = sizeof(outgoingData); // don't forget to pre-allocate memory
scanf_s("%255s", outgoingData, dataLength);
if (outgoingData != "")
{
if (strcmp(outgoingData, "OK") == 0) {
printf("Pengiriman selesai\n");
return NULL;
}
if (SP->WriteData(outgoingData, dataLength))
{
printf("Data send:%s\n", outgoingData);
}
}
Sleep(500);
}
// do stuff...
return NULL;
}
#if _MSC_VER && !__INTEL_COMPILER
#include <thread>
int main(int argc, char** argv) {
printf("Welcome to the serial test app!\n\n");
if (SP->IsConnected())
printf("Serial sudah terhubung\n");
int status;
std::thread thrd_1(baca,(void*)0);
std::thread thrd_2(tulis, (void*)0);
thrd_1.join();
thrd_2.join();
}
#else
// thread example
#include <pthread.h>
int main(int argc, char** argv) {
printf("Welcome to the serial test app!\n\n");
if (SP->IsConnected())
printf("Serial sudah terhubung\n");
pthread_t thrd_1;
pthread_t thrd_2;
int status;
pthread_create(&thrd_1, NULL, baca, (void*)0);
pthread_create(&thrd_2, NULL, tulis, (void*)0);
pthread_join(thrd_1, (void**)&status);
pthread_join(thrd_2, (void**)&status);
printf("Terima kasih");
return 0;
}
#endif
Pada tulisan Machine Learning #5 telah diceritakan tentang Neural Network dengan 2 input dan 1 output. Mari kita kembangkan jika menggunakan 1 input dan 2 output. Percobaan ini mengarah ke klasifikasi.
Sabagai gambaran apabila inputnya adalah suara yang diubah menjadi nilai dalam bentuk matrik x dan hasilnya adalah 2 output, yaitu output y= [0 0]. Output y = [1 0], jika hasil klasifikasinya mengarah pada output pertama, misalkan saya kata “YA”, dan outputnya y = [0 1] jika hasil klasifikasinya adalah output kedua, misalkan kata “Tidak”.
Dari model di atas, tentunya agak kesulitan untuk diterapkan di mikrokontroler. Hasil dari training dalam bentuk TFLite >5Mb. Padahal mikrokontroler, katakanlah BLE 33 Sense, tidak memiliki Flash Memori yang berkapasitas 5Mb
Cara yang pertama yaitu mengubah kuantisasi dari float menjadi int pada mikrokontoler. Berikut contoh perbandingan kuantisasi menggunakan float dibandingkan menggunakan int. Memang akurasi menjadi sedikit berubah, namun penggunaan memori jauh lebih kecil.
Menghilangkan parameter yang tidak begitu penting, dengan pruning.
Dan beberapa proses yang dapat disimpulkan seperti gambar berikut:
Dilihat dari situs resmi TensorFlow, saat ini board yang support dengan model training TensorFlowLite adalah board berikut:
Jadi mari kita gunakan yang saya punya, yaitu ESP-EYE (murah, 200an ribu) dan Nano 33 BLE Sense (mahal, 1,2 juta).
Untuk dapat menggunakan TinyML ada penjelasan di situs resminya, tapi cukup ribet. Mari gunakan milik Simone yang bernama EloquentTinyML. Siapkan dahulu library-nya melalui Library Manager
Selanjutnya pilih papan (board) yang tepat. Untuk Nano 33 BLE Sense lihat tutorialnya di tulisan Mencoba Nano 33 BLE Sense sedangkan jika menggunakan ESP-EYS, lihat tutorialnya di tulisan Memulai Percobaan ESP-CAM. Dicontohkan untuk kali ini kita gunakan Nano 33 BLE Sense:
Pada baris 2, isikan nama file hasil pengubahan tflile, misalkan hasilnya adalah sine_model.h Model yang akan digunakan adalah model 1 input dan 1 ouput sesuai pada artikel Machine Learning #3 Selanjutnya ketikkan jumlah input dan jumlah outputnya seperti yang dicontohkan di baris 4 dan 5, yaitu 1 input dan 1 output.
Di baris 8, adalah inisialisasi object EloquentTinyML sedangkan baris 13 adalah membaca model sine_model.h agar dapat diproses oleh library TinyML.
Untuk melihat hasil prediksi cukup gunakan .predict(nilai input) seperti yang terlihat di baris 21.
Saatnya upload skecth ke Nano 33 BLE Sense
Penampakan Nano 33 BLE Sense
Mari dilihat hasilnya, apakah mikrokontroler mampu memprediksi nilai y berdasarkan nilai input x? dimana rumus sebenarnya adalah y = sin(x). Mungkin ada sedikit selisih, namun untuk percobaan dengan 1 hidden layer ini bisa dimaklumi. Perlu banyak neuron dan hidden layer untuk mendapatkan nilai kesalahan (loss) yang sangat kecil.
Setelah mendapatkan model dari hasil training, model dapat disimpan ke file .tflite, file ini dapat kita gunakan untuk framework lain misalnya untuk mikrokontroller. Untuk membentuk file .tflite dari hasil training gunakan kode berikut:
# Convert model ke file tflite
tflite_model_name = 'sine_model' # .tflite
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_model = converter.convert()
#for 1.2 to 2.3
#open(tflite_model_name + '.tflite', 'wb').write(tflite_model)
#for 2.4 or later
with tf.io.gfile.GFile(tflite_model_name +'.tflite', 'wb') as f:
f.write(tflite_model)
Hasil dari code diatas adalah file sine_model.tflite atau dapat mnegubah nama filenya di baris 2
Karena mikrokontroler yang akan digunakan dibangun menggunakan bahasa C, maka perlu mengubah tflite menjadi file header agar dapat dikenali pada bahasa pemrograman C. Ada code fungsi (prosedur) yang sudah dibuat oleh pegiat machine learning, tinggal dipakai saja.
# Function: Convert some hex value into an array for C programming
def hex_to_c_array(hex_data, var_name):
c_str = ''
# Create header guard
c_str += '#ifndef ' + var_name.upper() + '_H\n'
c_str += '#define ' + var_name.upper() + '_H\n\n'
# Add array length at top of file
c_str += '\nunsigned int ' + var_name + '_len = ' + str(len(hex_data)) + ';\n'
# Declare C variable
c_str += 'unsigned char ' + var_name + '[] = {'
hex_array = []
for i, val in enumerate(hex_data) :
# Construct string from hex
hex_str = format(val, '#04x')
# Add formatting so each line stays within 80 characters
if (i + 1) < len(hex_data):
hex_str += ','
if (i + 1) % 12 == 0:
hex_str += '\n '
hex_array.append(hex_str)
# Add closing brace
c_str += '\n ' + format(' '.join(hex_array)) + '\n};\n\n'
# Close out header guard
c_str += '#endif //' + var_name.upper() + '_H'
return c_str
Selanjutnya, gunakan fungsi di atas untuk mengubah .tflite menjadi .h, nama filenya dapat diset pada baris ke-2. Kali ini dinamai dengan sine_model.h
# Write TFLite model to a C source (or header) file
c_model_name = 'sine_model' # .h
with open(c_model_name + '.h', 'w') as file:
file.write(hex_to_c_array(tflite_model, c_model_name))