Skip to content

Instantly share code, notes, and snippets.

View gotev's full-sized avatar

Aleksandar 'Alex' Gotev gotev

View GitHub Profile
@gotev
gotev / convert_pdf_to_text.py
Last active October 16, 2023 12:39
Extract Text from PDF containing images
# Requirements:
# pip install pdf2image pytesseract Pillow
#
import os
import glob
import sys
import pytesseract
from pdf2image import convert_from_path
from PIL import Image
@gotev
gotev / universalTest.swift
Last active December 4, 2022 16:35
Swift Multiplatform Experiments. Read comments below.
import Foundation
// needed for Linux
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
// New async await URLSession extensions are available solely on Apple platform
// so this polyfill it's necessary, otherwise the code does not compile on Linux
extension URLSession {
@gotev
gotev / reencode
Created November 19, 2022 10:10
Re-Encode Mp4 Video Files using H.264 and AAC audio, optimized for streaming
#!/bin/bash -e
# Re-Encode Mp4 Video Files using H.264 and AAC audio, optimized for streaming
# Credits: https://superuser.com/a/1551095
# -c:v libx264 selects the video encoder libx264, which is a H.264 encoder.
# -preset slow selects the slow x264 encoding preset. Default preset is medium. Use the slowest preset that you have patience for.
# -crf 20 selects a CRF value of 20 which will result in a high quality output. Default value is 23. A lower value is a higher quality. Use the highest value that gives an acceptable quality.
# -c:a aac selects the audio encoder aac, which is the built-in FFmpeg AAC encoder.
# -b:a 160k encodes the audio with a bitrate of 160k.
# -vf format=yuv420p chooses YUV 4:2:0 chroma-subsampling which is recommended for H.264 compatibility.
@gotev
gotev / video-files-duration
Last active November 15, 2022 00:00
List mp4 files in a folder and get duration for each file and total duration
#!/usr/bin/env python3
import os
import re
import pathlib
import ffmpeg
import time
files = pathlib.Path('.').glob('*.mp4')
files = sorted(files, key=lambda x: float(re.findall("(\d+)", os.path.basename(x))[0]))
@gotev
gotev / extract-key-frames
Last active November 14, 2022 08:05
Extract Frames from a video. Useful to extract presentation slides and key moments.
#!/bin/bash -e
# Extract Key Frames from a video and print timestamp on each frame (works with ffmpeg version 5.1.2)
#
# Credits:
# - https://jdhao.github.io/2021/12/25/ffmpeg-extract-key-frame-video/
# - https://superuser.com/questions/575854/can-ffmpeg-extract-images-from-a-video-with-timestamps
#
# First parameter: input video
# Second parameter: output directory
# Example ./extract-key-frames myvideo.mp4 outdir/
@gotev
gotev / htmlWithSwift.swift
Last active May 5, 2022 11:40
Generate HTML with Swift. Just copy and paste the code below in a Swift Playground and have fun.
import Foundation
extension Sequence where Element: Hashable {
func uniqued() -> [Element] {
var set = Set<Element>()
return filter { set.insert($0).inserted }
}
}
public extension StringProtocol {
@gotev
gotev / configure-ssh-certs.sh
Last active April 28, 2021 23:37
macOS GitHub SSH Certificates Helper
#!/bin/bash -e
echo "macOS Helper to configure SSH Key to use with GitHub"
echo "based off of instructions reported at:"
echo "https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account"
echo
if [[ "$OSTYPE" != "darwin"* ]]; then
echo "This script is designed for macOS only..."
echo "exiting"
@gotev
gotev / SafeClickListener.kt
Created April 8, 2020 17:25
Android Safe Click Listener
import android.os.SystemClock
import android.view.View
/**
* Implements the "throttle first" mechanism for click listeners, to prevent double taps.
*
* How it works:
* - Define a sampling window time (default: 500ms)
* - when you click at time T0, the first click gets dispatched and the subsequent ones happening
* between T0 and T0 + WindowTime gets ignored
@gotev
gotev / ISO8601DateJSONDecoder.swift
Created February 21, 2020 18:46
iOS ISO8601 Date JSON Decoder
let jsonDecoder: JSONDecoder = {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let formatter1 = ISO8601DateFormatter()
formatter1.formatOptions = [.withInternetDateTime]
let formatter2 = ISO8601DateFormatter()
formatter2.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
guard let date = formatter1.date(from: string) ?? formatter2.date(from: string) else {
@gotev
gotev / NavigationBottomBarSectionsStateKeeperWorkaround.kt
Last active June 12, 2023 16:08
JetPack Bottom Bar Navigation with Sections State
package jetpack.navigation.workaround
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.navigation.NavController
import androidx.navigation.ui.setupActionBarWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import java.lang.ref.WeakReference