螢幕錄影新選擇:簡單、方便、免費
現在的螢幕錄影工具多樣,但安裝麻煩、操作複雜讓人卻步。我們推出了一款全新的螢幕錄影程式,專為追求簡單和效率的你設計。
1. 免安裝
無需安裝程式。解壓縮後點兩下就可以開始使用
2. 可選取錄影範圍
自由選擇全螢幕、特定視窗或自定義區域,靈活應對各種錄影需求。
3. 簡單易用
直觀的介面設計,讓你輕鬆上手,無需學習成本。
4. 免費下載
完全免費,無隱藏費用,下載後即可使用。
結語
這款螢幕錄影程式是你的最佳選擇,免安裝、靈活、易用又免費!
現在的螢幕錄影工具多樣,但安裝麻煩、操作複雜讓人卻步。我們推出了一款全新的螢幕錄影程式,專為追求簡單和效率的你設計。
無需安裝程式。解壓縮後點兩下就可以開始使用
自由選擇全螢幕、特定視窗或自定義區域,靈活應對各種錄影需求。
直觀的介面設計,讓你輕鬆上手,無需學習成本。
完全免費,無隱藏費用,下載後即可使用。
這款螢幕錄影程式是你的最佳選擇,免安裝、靈活、易用又免費!
在/var/www/html 建立 .htaccess
加入以下內容
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
修改apache2.conf
/etc/apache2/apache2.conf
加入以下內容
<Directory /var/www/html/>
Option Indexes FollowSymbLinks
AllowOverride None
Require all granted
</Directory>
重新啟動Apache2
sudo a2enmod rewrite
sudo service apache2 restart
Environment
Ubuntu 20.4
Python 3.8
iOS 17.5.1
Install
1. python3 -m pip install -U pymobiledevice3
2. sudo apt install libusb-1.0.0-dev openssl
3. pip3 install --upgrade pymobiledevice3 (4.11)
4. pip3 install --upgrade click (8.1.7)
5. pip3 install --upgrade pygments (2.18)
Simulate Location
pymobiledevice3 mounter auto-mount
pymobiledevice3 lockdown start-tunnel
copy "--rsd xxx..." text
pymobiledevice3 developer dvt simulate-location set <rsd string> -- 40.69008 -74.045843
Reference
https://github.com/doronz88/pymobiledevice3
open /boot/config.txt
origin
dtoverlay=vc4-kms-v3d
changes to
dtoverlay=vc4-fkms-v3d
壓縮
tar czvf <filename>.tar.gz <directory>
zip -r <filename>.zip <directory>
解壓縮
tar xzvf <filename>.tar.gz
import tkinter as tk
def on_closing():
root.destroy()
class MainWindow(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
root = MainWindow()
root.title('Main Window')
root.protocol("WM_DELETE_WINDOW", on_closing)
root.geometry('640x480')
root.mainloop()
在 <home>/.config 新增 autostart 目錄
touch <home>/.config/autostart/<program name>.desktop
在<program name>.desktop加入以下內容
[Desktop Entry]
Name=<program name>
Exec=<path to>/<your program execuable>
Type=application
就可以了
RaspberryPi也一樣可以這樣處理
首先到 mbed online IDE
https://ide.mbed.com/compiler/
第一次使用經過註冊程序就會看到IDE畫面
接著開始新增專案 mbed沒有提供STM32F4 DISC1版本
但是 Seeed Arch Max 剛好是使用 STMD32F407 這顆 MCU
所以選取 Seeed Arch Max 當作專案 platform
專案 template 選取 Blinky LED Hello World
程式碼修改如下:
#include "mbed.h"
#define BLINKING_RATE 500
int main()
{
// Initialise PD12 as an output
DigitalOut gLED(PD_12);
while (true) {
gLED = !gLED;
ThisThread::sleep_for(BLINKING_RATE);
}
}
按下介面上的 Compile 按鈕
mbed online IDE 會在完成後跳出下載 binary 檔案
將這個 .bin 檔存入 STM32F4 DISC1 的資料夾
最後就會看到 PD12 開始閃爍囉!
Reference
https://www.hackster.io/PSoC_Rocks/easy-programming-stm32f407-discovery-board-with-mbed-8ead8e
環境: Ubuntu 18.04 Server
第一次登入EC2後
以上完成wordpress需要的軟體。
在使用mysql server前先進行初始化。
mysql> USE mysql;
mysql> UPDATE user SET plugin='mysql_native_password' WHERE User='root';
將原本root的登入方式(auth_socket)改為mysql_native_password
mysql> CREATE DATABASE new_db;
mysql> CREATE USER 'new_user'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON new_db.* TO 'new_user'@'localhost';
建立wordpress的資料庫(new_db)並設定資料庫權限給新建的使用者帳戶(new_user),之後wordpress安裝時需要輸入此使用者帳戶及密碼。
接下來到wordpress.org下載最新版本(目前為5.5.1)的wordpress
% cd /var/www/html
% sudo unzip wordpress-5.5.1.zip
% sudo chown -R www-data. wordpress/
最後打開AWS EC2的security group的port 80
連入網站即可開始進行wordpress的最後設定。
常用的解決方法
sudo mount -o remount,rw /Download driver from:
https://github.com/ulli-kroll/rtl8188fu
After ‘make’:
sudo modprobe cfg80211
sudo insmod rtl8188fu.ko
Connect to AP:
nmcli r wifi on
nmcli d wifi list
nmcli d wifi connect “ssid” password “pw”
我在下指令 gradlew signingReport 時, 出現了這個錯誤
error occurred during initialization of vm could not reserve enough space for 1572864kb object heap
原來我安裝到了 32bit 版本的 JDK
所以 allocate 過大的 heap size 會出現問題
解決的方法當然是改成安裝 64bit JDK 或者如果是用 Android Studio 的
可以在 gradle.properties 檔修改成
org.gradle.jvmargs=-Xmx512M
就可以了
PS. 如果下指令 java -d32 -version 會正常出現版本說明的話 那就是安裝到 32bit JDK
ZYNQ add SPI interface
Customize SPI device tree for petalinux
After update HDF and execute command: petalinux-config –get-hw-description=<HDF Directory>
In components/plnx_workspace/device-tree/device-tree/pl.dtsi, will produce SPI device node automatically as below:
Modify project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi as below
Enable SPI device driver
$ petalinux-config -c kernel
Go to Device Drivers -> SPI Support -> User mode SPI device driver support and enable it.
Use spidev_test.c to verify the SPI interface.
$ ls /dev/spi*
$ gcc spidev_test.c -o spidev_test
$ ./spidev_test -D /dev/spidev1.0
自工作以來,好像每隔一陣子就有機會用到ffmpeg來做視訊處理
像是 android app, embedded linux 或是windows上的視訊播放程式
所以記錄一下這次 Windows 平台搭配 VS 2019 的專案建置流程
3. 複製ffmpeg zip裡的 include/lib 資料夾到<project>目錄下
5. 複製ffmpeg zip裡 include/bin 的 *.dll 到 <project>/out/build/x64-Debug
6. 複製sdl2 zip裡的 include 資料夾到 <project>/include/ 下更名為 SDL2
7. 複製sdl2 zip裡的 lib/SDL2.lib 到 <project>/lib
8. 複製sdl2 zip裡的 lib/SDL2.dll 到 <project>/out/build/x64-Debug
最後配置 CMakeLists.txt 如下
cmake_minimum_required (VERSION 3.8)
project ("ffmpeg-test")
include_directories("include")
link_directories("lib")
add_executable (ffmpeg-test "ffmpeg-test.cpp" "ffmpeg-test.h")
target_link_libraries(
ffmpeg-test
avcodec
avdevice
avfilter
avformat
avutil
postproc
swresample
swscale
SDL2
)
接下來我們就可以用一個簡單的 Hello World 驗証專案設定是否正常
#define SDL_MAIN_HANDLED // Important!
#include "ffmpeg-test.h"
using namespace std;
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/avstring.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_thread.h>
}
int main()
{
const char* version = av_version_info();
cout << "FFmpeg version: " << version << endl;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cout << "SDL could not initialize! SDL_Error: " << SDL_GetError() << endl;
}
else {
cout << "SDL Initialize OK!" << endl;
}
return 0;
}
現在 open source 社群非常發達,不管是軟體還是硬體上,開發的平台或工具越來越多樣,像這樣的系統架構只要靠著各站點約一百行左右的程式碼就可以完成,真的是非常方便。這次實驗將會用到的技術包括:
Python, Node.js, HTML and Javascript.
首先,要能在 Raspberry Pi 3 上擷取一張照片,使用的 webcam 當然要支援 v4l2 驅動及 UVC 相容,這樣我們就可以很方便的用 opencv-python 模組來抓影像。
# snapshot.py
import cv2
def capture():
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cv2.imwrite("snap.jpg", frame)
cap.release()
capture()
接下來,我們需要一些網際網路及 TCP/IP 的觀念。
我們的 Raspberry Pi 在家中使用 WiFi 上網,屬於 Private Network,身在Public Network 的網站是無法直接透過 IP 位址找到 Raspberry Pi。所以我們要在Raspberry Pi 和網站中間保持一條 TCP 連線,當使用者按下拍照鈕後,網站可以透過這條連線通知 Raspberry Pi 進行拍照及上傳。
我採用 Node.js 開發 camera client 程式,當然也可以用 python 來實作,不過用Node.js 的話,程式會更加簡短。
// camera_client.js
const net = require('net');
const exec = require('child_process').exec;
const request = require('request');
const fs = require('fs');
const PORT = 18080; // web server tcp port
const HOST = '<web server ip>';
var client = new net.Socket();
client.connect(POST, HOST, function() {
console.log('Connected');
});
client.on('data', function(msg) {
if (msg == "snapshot") {
console.log('Snaphsot');
}
});
client.on('close', function() {
console.log('Connection closed');
client = null;
});
當 camera_client.js 收到 ‘snapshot’ 訊息後,就要執行 snapshot.py 來拍照並存成 snap.jpg 檔。
exec('python3 snapshot.py', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log('Snaphsot...done');
});
存檔完成後,我們可以用 request 模組,以 HTTP 協定的方式上傳 snap.jpg 檔。
var req = request.post(HOST + '/fileupload', function (err, resp, body) {
if (err) {
console.log('Error');
}
});
var form = req.form();
form.append('filetoupload', fs.createReadStream('snap.jpg'), {
name: 'snap.jpg'
});
以上在 Raspberry Pi 上的開發就完成了。
網站端的開發我一樣採用 Node.js,它可以很快速的建立一個簡單的 web server 提供使用者一個簡易的網頁,同時也可以接收 camera_client.js 的 TCP 連線。
首先我們建立一個 index.html 網頁提供使用者檢視照片及一個拍照按鈕。
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
...
function snapshot() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
setTimeout(reloadSnapshot, 1000);
}
};
xhttp.open("GET", "snapshot", true);
xhttp.send();
}
</script>
<body>
<img id="snap-img" src="snap.jpg" style="max-width:100%;height:auto;"/><br/>
<input id="snap-btn" type="button" value="Snapshot" onclick="snapshot()" />
</body>
</html>
這個網頁會向 web server 下載 snap.jpg 然後當使用者下載拍照鈕後,會用 AJAX發出 GET request 到 web server。接下來我們實作 camera_server.js 來處理及回應這兩個動作。
// camera_server.js
const net = require('net');
const http = require('http');
const fs = require('fs');
const formidable = require('formidable');
const HOST = '0.0.0.0';
const requestListener = function (req, res) {
if (req.url == '/') {
var html = fs.readFileSync('index.html');
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(html);
}
else if (req.url.startsWith('/snap.jpg')) {
if (!fs.existsSync('snap.jpg')) {
res.setHeader("Content-Type", "image/jpeg");
res.writeHead(400);
res.end();
return;
}
var img = fs.readFileSync('snap.jpg');
res.setHeader("Content-Type", "image/jpeg");
res.writeHead(200);
res.end(img);
}
...
}
const web = http.createServer(requestListener);
web.listen(8080, HOST, () => {
console.log('Web Server is running');
});
Node.js 強大的 http 模組讓我們一秒變身簡易 web server 我們可以建立 Request Listener 來處理所以網頁的 request。以 req.url 來判斷要回應 index.html 或 snap.jpg。
前面提到過 camera_client.js 要跟 camera_server.js 保持 TCP 連線,所以現在在 camera_server.js 加入一個 socket server 並開啟 TCP_PORT 等待 camera_client.js 連入。
var cameraClient = null;
const TCP_PORT = 8080;
var server = net.createServer();
server.on('connection', handleConnection);
server.listen(TCP_PORT, HOST, function() {
console.log('TCP Server is running');
});
function handleConnection(conn) {
cameraClient = conn;
var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
console.log('new client connection from %s', remoteAddress);
conn.on('data', onReceiveData);
conn.once('close', onConnClose);
conn.on('error', onConnError);
function onReceiveData(msg) {
};
function onConnClose() {
console.log('connection from %s closed', remoteAddress);
cameraClient = null;
};
function onConnError(err) {
console.log('connection from %s error', remoteAddress);
cameraClient = null;
};
}
接下來我們在 camera_server.js 的 Request Listener 收到 snapshot request 後,我們就可以送出 ‘snapshot’ 訊息到 camera_client.js。然後我用 formidable 模組處理 camera_client.js 上傳檔案的動作。
...
else if (req.url == '/snapshot') {
// send 'snapshot' message to camera_client.js
cameraClient.write('snapshot');
if (fs.existsSync('snap.jpg'))
fs.unlinkSync('snap.jpg');
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end();
}
else if (req.url == '/fileupload') {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var oldpath = files.filetoupload.path;
var newpath = './' + files.filetoupload.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded');
res.end();
});
});
}
...
最後比較麻煩的是,前端網頁在送出 snapshot GET request 後要如何知道新的影像己經上傳完成?我們可以在 index.html 中送出 ‘snapshot’ 訊息後設定一個 timer 固定一小段時間就去詢問 camera_server.js 上的 snap.jpg 是否更新了。
...
function reloadSnapshot() {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "reload", false);
xhttp.send();
if (xhttp.status != 200) {
setTimeout(reloadSnapshot, 1000);
return;
}
document.getElementById('snap-img').src = "snap.jpg?random="+new
Date().getTime();
}
...
我們用 setTimeout() 每秒送出 reload 訊息去詢問 camera_server.js 是否有更新影像,若有的話,這裡有個小技巧,用 snap.jpg?random=… 的方式強迫瀏覽器更新影像。
最後在 camera_server.js 的 Request Listener加入 reload 訊息處理。如果 snap.jpg 檔案不存在則回應 404。
...
else if (req.url == '/reload') {
if (!fs.existsSync('snap.jpg')) {
res.setHeader("Content-Type", "text/html");
res.writeHead(404);
res.end();
return;
}
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end();
}
...
到這裡,我們就用一百行左右的程式碼完成了簡易的遠端監看系統。在 Raspberry Pi 跟 web server 上分別啟動程式。
Web-Server# node camera-server.js
RPi# node camera-client.js
用瀏覽器連線到 http://<host_ip>:<web_port>/ 就可以開始使用囉。
完整原始碼請到 Github 下載。
Let’s Encrypt 組織免費提供瀏覽器認可的SSL憑證
不過這項服務每3個月需要重複執行申請手續
若想要快速的完成申請, 我們可以安裝 certbot 這項工具來幫助我們.
sudo apt install certbot python3-certbot-apache
sudo certbot --apache
在經過一些安裝步驟後, 最後只要下指令
sudo certbot renew
cerbot 就可以自動幫我們完成SSL憑證申請手續並自動放到apache web server下的目錄.
certbot 還有自動更新功能, 可以用以下指令檢查自動更新功能是否正常
sudo systemctl status certbot.timer
不同的作業系統在 certbot 官方 也都有提供完整的安裝指引.
網路上雖然免費的螢幕錄影程式很多
但是大多不是免安裝的綠色軟體
而且有的要配合網站使用,有的要申請一個帳號才能下載
於是乾脆自己做了一個簡單的螢幕錄影程式
雖然只能全螢幕錄影,不過對我來說可以錄影就好
剪輯或是轉檔有其它的軟體可以處理。
下載點
程式開發幕後
我常說看似簡單的程式,真的要做到推出給大眾使用
其實還是需要一番功夫的
螢幕錄影程式短短不到一百行程式就完成
但是在程式打包封裝上,除了常用的 pyinstaller
我推薦搭配使用 auto-py-to-exe
它可以說是 pyinstaller 的 GUI 版本
pyinstaller 在下 –add-data 參數時,因為要加上路徑的關係,整個指令變得很長很複雜
有了 auto-py-to-exe 就變得簡單多了
在加入程式圖示(.ico檔)時,需要把 .ico 加入圖示及加入附加檔案
若是想打包成 –onefile 就需要在程式裡另外處理了
原因請參考 stackoverflow
首先加入
def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ try: # PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path)
原先載入圖示的程式碼
window.wm_iconbitmap('logo.ico')改為
window.wm_iconbitmap(resource_path('logo.ico'))就可以了!
1. 使用 UART TO USB Dongle
2. 接線
5V <------> 5V
GND <-----> GND (與5V同一側的GND)
TX <-----> U0R
RX <------> U0T
ESP32CAM上的IO0接上自己的GND
3. Arduino IDE
新增額外的開發板管理員網址
https://raw.githubusercontent.com/espressif/arduino-esp32/master/package.json
新增開發板管理員
螢幕錄影新選擇:簡單、方便、免費 現在的螢幕錄影工具多樣,但安裝麻煩、操作複雜讓人卻步。我們推出了一款全新的螢幕錄影程式,專為追求簡單和效率的你設計。 1. 免安裝 無需安裝程式。解壓縮後點兩下就可以開始使用 2. 可選取錄影範圍 自由選擇全螢幕、特定視窗或自定義區域,靈活應...