From 77b69076e4b23db9e173f41f8561a0a0daf06fce Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 04:44:48 -0600 Subject: [PATCH 01/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2eb18d8..d9d9399 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Ultimate Vocal Remover GUI (Develop Version) +# Ultimate Vocal Remover GUI ***NEW VERSION COMING 11/14/2020!*** From 220da7e5a443213167f506d3e3976f68d7c3236e Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 04:45:53 -0600 Subject: [PATCH 02/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9d9399..e8d4117 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ***NEW VERSION COMING 11/14/2020!*** -![alt text](https://github.com/Anjok07/ultimatevocalremovergui/blob/develop/Images/UVR-app.jpg) +![alt text](https://raw.githubusercontent.com/Anjok07/ultimatevocalremovergui/master/Images/UVR-App.jpg) This is a deep-learning-based tool that extracts the instrumental from a track containing vocals. This project is a GUI version of the vocal remover created and posted by tsurumeso. This would not have been possible without tsurumeso's work and dedication! You can find tsurumeso's original command line version [here](https://github.com/tsurumeso/vocal-remover) From 03b17c5c7119d26f2f9febf0389755762a19a110 Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 13:52:31 -0600 Subject: [PATCH 03/12] Delete augment.py --- augment.py | 76 ------------------------------------------------------ 1 file changed, 76 deletions(-) delete mode 100644 augment.py diff --git a/augment.py b/augment.py deleted file mode 100644 index 467230a..0000000 --- a/augment.py +++ /dev/null @@ -1,76 +0,0 @@ -import argparse -import os -import subprocess - -import librosa -import numpy as np -import soundfile as sf -from tqdm import tqdm - -from lib import spec_utils - - -if __name__ == '__main__': - p = argparse.ArgumentParser() - p.add_argument('--sr', '-r', type=int, default=44100) - p.add_argument('--hop_length', '-l', type=int, default=1024) - p.add_argument('--pitch', '-p', type=int, default=-2) - p.add_argument('--mixture_dataset', '-m', required=True) - p.add_argument('--instrumental_dataset', '-i', required=True) - args = p.parse_args() - - input_exts = ['.wav', '.m4a', '.3gp', '.oma', '.mp3', '.mp4'] - X_list = sorted([ - os.path.join(args.mixture_dataset, fname) - for fname in os.listdir(args.mixture_dataset) - if os.path.splitext(fname)[1] in input_exts]) - y_list = sorted([ - os.path.join(args.instrumental_dataset, fname) - for fname in os.listdir(args.instrumental_dataset) - if os.path.splitext(fname)[1] in input_exts]) - - input_i = 'input_i_{}.wav'.format(args.pitch) - input_v = 'input_v_{}.wav'.format(args.pitch) - output_i = 'output_i_{}.wav'.format(args.pitch) - output_v = 'output_v_{}.wav'.format(args.pitch) - cmd_i = 'soundstretch {} {} -pitch={}'.format(input_i, output_i, args.pitch) - cmd_v = 'soundstretch {} {} -pitch={}'.format(input_v, output_v, args.pitch) - suffix = '_pitch{}.npy'.format(args.pitch) - - filelist = list(zip(X_list, y_list)) - for mix_path, inst_path in tqdm(filelist): - X, _ = librosa.load( - mix_path, args.sr, False, dtype=np.float32, res_type='kaiser_fast') - y, _ = librosa.load( - inst_path, args.sr, False, dtype=np.float32, res_type='kaiser_fast') - - X, _ = librosa.effects.trim(X) - y, _ = librosa.effects.trim(y) - X, y = spec_utils.align_wave_head_and_tail(X, y, args.sr) - - v = X - y - sf.write(input_i, y.T, args.sr) - sf.write(input_v, v.T, args.sr) - subprocess.call(cmd_i, stderr=subprocess.DEVNULL) - subprocess.call(cmd_v, stderr=subprocess.DEVNULL) - - y, _ = librosa.load( - output_i, args.sr, False, dtype=np.float32, res_type='kaiser_fast') - v, _ = librosa.load( - output_v, args.sr, False, dtype=np.float32, res_type='kaiser_fast') - X = y + v - - spec = spec_utils.calc_spec(X, args.hop_length) - basename, _ = os.path.splitext(os.path.basename(mix_path)) - outpath = os.path.join(args.mixture_dataset, basename + suffix) - np.save(outpath, np.abs(spec)) - - spec = spec_utils.calc_spec(y, args.hop_length) - basename, _ = os.path.splitext(os.path.basename(inst_path)) - outpath = os.path.join(args.instrumental_dataset, basename + suffix) - np.save(outpath, np.abs(spec)) - - os.remove(input_i) - os.remove(input_v) - os.remove(output_i) - os.remove(output_v) From fd3171a93467aaaedebef8fcf7da3a7c91ff4d9d Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 13:52:44 -0600 Subject: [PATCH 04/12] Delete train.py --- train.py | 223 ------------------------------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 train.py diff --git a/train.py b/train.py deleted file mode 100644 index 420f487..0000000 --- a/train.py +++ /dev/null @@ -1,223 +0,0 @@ -import argparse -from datetime import datetime as dt -import gc -import json -import os -import random - -import numpy as np -import torch -import torch.nn as nn - -from lib import dataset -from lib import nets -from lib import spec_utils - - -def train_val_split(mix_dir, inst_dir, val_rate, val_filelist_json): - input_exts = ['.wav', '.m4a', '.3gp', '.oma', '.mp3', '.mp4'] - X_list = sorted([ - os.path.join(mix_dir, fname) - for fname in os.listdir(mix_dir) - if os.path.splitext(fname)[1] in input_exts]) - y_list = sorted([ - os.path.join(inst_dir, fname) - for fname in os.listdir(inst_dir) - if os.path.splitext(fname)[1] in input_exts]) - - filelist = list(zip(X_list, y_list)) - random.shuffle(filelist) - - val_filelist = [] - if val_filelist_json is not None: - with open(val_filelist_json, 'r', encoding='utf8') as f: - val_filelist = json.load(f) - - if len(val_filelist) == 0: - val_size = int(len(filelist) * val_rate) - train_filelist = filelist[:-val_size] - val_filelist = filelist[-val_size:] - else: - train_filelist = [ - pair for pair in filelist - if list(pair) not in val_filelist] - - return train_filelist, val_filelist - - -def train_inner_epoch(X_train, y_train, model, optimizer, batchsize, instance_loss): - sum_loss = 0 - model.train() - aux_crit = nn.L1Loss() - criterion = nn.L1Loss(reduction='none') - perm = np.random.permutation(len(X_train)) - for i in range(0, len(X_train), batchsize): - local_perm = perm[i: i + batchsize] - X_batch = torch.from_numpy(X_train[local_perm]).cpu() - y_batch = torch.from_numpy(y_train[local_perm]).cpu() - - model.zero_grad() - mask, aux = model(X_batch) - - aux_loss = aux_crit(X_batch * aux, y_batch) - X_batch = spec_utils.crop_center(mask, X_batch, False) - y_batch = spec_utils.crop_center(mask, y_batch, False) - abs_diff = criterion(X_batch * mask, y_batch) - - loss = abs_diff.mean() * 0.9 + aux_loss * 0.1 - loss.backward() - optimizer.step() - - abs_diff_np = abs_diff.detach().cpu().numpy() - instance_loss[local_perm] += abs_diff_np.mean(axis=(1, 2, 3)) - sum_loss += float(loss.detach().cpu().numpy()) * len(X_batch) - - return sum_loss / len(X_train) - - -def val_inner_epoch(dataloader, model): - sum_loss = 0 - model.eval() - criterion = nn.L1Loss() - with torch.no_grad(): - for X_batch, y_batch in dataloader: - X_batch = X_batch.cpu() - y_batch = y_batch.cpu() - mask = model.predict(X_batch) - X_batch = spec_utils.crop_center(mask, X_batch, False) - y_batch = spec_utils.crop_center(mask, y_batch, False) - - loss = criterion(X_batch * mask, y_batch) - sum_loss += float(loss.detach().cpu().numpy()) * len(X_batch) - - return sum_loss / len(dataloader.dataset) - - -def main(): - p = argparse.ArgumentParser() - p.add_argument('--gpu', '-g', type=int, default=-1) - p.add_argument('--seed', '-s', type=int, default=2019) - p.add_argument('--sr', '-r', type=int, default=44100) - p.add_argument('--hop_length', '-l', type=int, default=1024) - p.add_argument('--mixture_dataset', '-m', required=True) - p.add_argument('--instrumental_dataset', '-i', required=True) - p.add_argument('--learning_rate', type=float, default=0.001) - p.add_argument('--lr_min', type=float, default=0.0001) - p.add_argument('--lr_decay_factor', type=float, default=0.9) - p.add_argument('--lr_decay_patience', type=int, default=6) - p.add_argument('--batchsize', '-B', type=int, default=4) - p.add_argument('--cropsize', '-c', type=int, default=256) - p.add_argument('--val_rate', '-v', type=float, default=0.1) - p.add_argument('--val_filelist', '-V', type=str, default=None) - p.add_argument('--val_batchsize', '-b', type=int, default=4) - p.add_argument('--val_cropsize', '-C', type=int, default=512) - p.add_argument('--patches', '-p', type=int, default=16) - p.add_argument('--epoch', '-E', type=int, default=100) - p.add_argument('--inner_epoch', '-e', type=int, default=4) - p.add_argument('--oracle_rate', '-O', type=float, default=0) - p.add_argument('--oracle_drop_rate', '-o', type=float, default=0.5) - p.add_argument('--mixup_rate', '-M', type=float, default=0.0) - p.add_argument('--mixup_alpha', '-a', type=float, default=1.0) - p.add_argument('--pretrained_model', '-P', type=str, default=None) - p.add_argument('--debug', '-d', action='store_true') - args = p.parse_args() - - random.seed(args.seed) - np.random.seed(args.seed) - torch.manual_seed(args.seed) - timestamp = dt.now().strftime('%Y%m%d%H%M%S') - - model = nets.CascadedASPPNet() - if args.pretrained_model is not None: - model.load_state_dict(torch.load(args.pretrained_model)) - if args.gpu >= 0: - model.cuda() - - optimizer = torch.optim.Adam(model.parameters(), lr=args.learning_rate) - scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau( - optimizer, - factor=args.lr_decay_factor, - patience=args.lr_decay_patience, - min_lr=args.lr_min, - verbose=True) - - train_filelist, val_filelist = train_val_split( - mix_dir=args.mixture_dataset, - inst_dir=args.instrumental_dataset, - val_rate=args.val_rate, - val_filelist_json=args.val_filelist) - - if args.debug: - print('### DEBUG MODE') - train_filelist = train_filelist[:1] - val_filelist = val_filelist[:1] - - with open('val_{}.json'.format(timestamp), 'w', encoding='utf8') as f: - json.dump(val_filelist, f, ensure_ascii=False) - - for i, (X_fname, y_fname) in enumerate(val_filelist): - print(i + 1, os.path.basename(X_fname), os.path.basename(y_fname)) - - val_dataset = dataset.make_validation_set( - filelist=val_filelist, - cropsize=args.val_cropsize, - sr=args.sr, - hop_length=args.hop_length, - offset=model.offset) - val_dataloader = torch.utils.data.DataLoader( - dataset=val_dataset, - batch_size=args.val_batchsize, - shuffle=False, - num_workers=4) - - log = [] - oracle_X = None - oracle_y = None - best_loss = np.inf - for epoch in range(args.epoch): - X_train, y_train = dataset.make_training_set( - train_filelist, args.cropsize, args.patches, args.sr, args.hop_length, model.offset) - - X_train, y_train = dataset.mixup_generator( - X_train, y_train, args.mixup_rate, args.mixup_alpha) - - if oracle_X is not None and oracle_y is not None: - perm = np.random.permutation(len(oracle_X)) - X_train[perm] = oracle_X - y_train[perm] = oracle_y - - print('# epoch', epoch) - instance_loss = np.zeros(len(X_train), dtype=np.float32) - for inner_epoch in range(args.inner_epoch): - print(' * inner epoch {}'.format(inner_epoch)) - train_loss = train_inner_epoch( - X_train, y_train, model, optimizer, args.batchsize, instance_loss) - val_loss = val_inner_epoch(val_dataloader, model) - - print(' * training loss = {:.6f}, validation loss = {:.6f}' - .format(train_loss * 1000, val_loss * 1000)) - - scheduler.step(val_loss) - - if val_loss < best_loss: - best_loss = val_loss - print(' * best validation loss') - model_path = 'models/model_iter{}.pth'.format(epoch) - torch.save(model.state_dict(), model_path) - - log.append([train_loss, val_loss]) - with open('log_{}.json'.format(timestamp), 'w', encoding='utf8') as f: - json.dump(log, f, ensure_ascii=False) - - if args.oracle_rate > 0: - instance_loss /= args.inner_epoch - oracle_X, oracle_y, idx = dataset.get_oracle_data( - X_train, y_train, instance_loss, args.oracle_rate, args.oracle_drop_rate) - print(' * oracle loss = {:.6f}'.format(instance_loss[idx].mean())) - - del X_train, y_train - gc.collect() - - -if __name__ == '__main__': - main() From 979ae3913538793b7c2d4b9a06fc8fc9f6da6d32 Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 13:53:02 -0600 Subject: [PATCH 05/12] Delete Instrumentals Go Here.txt --- dataset/instruments/Instrumentals Go Here.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 dataset/instruments/Instrumentals Go Here.txt diff --git a/dataset/instruments/Instrumentals Go Here.txt b/dataset/instruments/Instrumentals Go Here.txt deleted file mode 100644 index ef28293..0000000 --- a/dataset/instruments/Instrumentals Go Here.txt +++ /dev/null @@ -1 +0,0 @@ -Instrumentals Go Here \ No newline at end of file From a064f420534fe51b244913038998d16f8548f5c5 Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 13:53:14 -0600 Subject: [PATCH 06/12] Delete Mixtures Go Here.txt --- dataset/mixtures/Mixtures Go Here.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 dataset/mixtures/Mixtures Go Here.txt diff --git a/dataset/mixtures/Mixtures Go Here.txt b/dataset/mixtures/Mixtures Go Here.txt deleted file mode 100644 index 1bda6e8..0000000 --- a/dataset/mixtures/Mixtures Go Here.txt +++ /dev/null @@ -1 +0,0 @@ -Mixtures Go Here \ No newline at end of file From d70c93602b08e4d7a929b687b2c9ed5a666c6458 Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 15:27:07 -0600 Subject: [PATCH 07/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8d4117..0dc7867 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ pip install torch==1.5.0+cu101 torchvision==0.6.0+cu101 -f https://download.pyto ``` pip install torch==1.5.0+cpu torchvision==0.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html ``` -- The rest need to be installed regardless! - +- The rest need to be installed as well - ``` pip install Pillow From 6bf2344edc00d669d6c2522bde7e64fa9eeaa354 Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 19:31:57 -0600 Subject: [PATCH 08/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dc7867..b1c1dcf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![alt text](https://raw.githubusercontent.com/Anjok07/ultimatevocalremovergui/master/Images/UVR-App.jpg) -This is a deep-learning-based tool that extracts the instrumental from a track containing vocals. This project is a GUI version of the vocal remover created and posted by tsurumeso. This would not have been possible without tsurumeso's work and dedication! You can find tsurumeso's original command line version [here](https://github.com/tsurumeso/vocal-remover) +This project is a GUI version of the vocal remover created and posted by tsurumeso. This is a deep-learning-based tool that extracts the instrumental from a track containing vocals. This would not have been possible without tsurumeso's work and dedication! You can find tsurumeso's original command line version [here](https://github.com/tsurumeso/vocal-remover) ## Installation From 6b1917668ff8ded0059ae77293068a890637bdbf Mon Sep 17 00:00:00 2001 From: Anjok07 <68268275+Anjok07@users.noreply.github.com> Date: Mon, 9 Nov 2020 20:58:56 -0600 Subject: [PATCH 09/12] Update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b1c1dcf..734156e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Ultimate Vocal Remover GUI -***NEW VERSION COMING 11/14/2020!*** +***NEW VERSION WITH BRAND NEW MODELS COMING 11/14/2020! SEE THE BETA BRANCH FOR MORE DETAILS!*** ![alt text](https://raw.githubusercontent.com/Anjok07/ultimatevocalremovergui/master/Images/UVR-App.jpg) -This project is a GUI version of the vocal remover created and posted by tsurumeso. This is a deep-learning-based tool that extracts the instrumental from a track containing vocals. This would not have been possible without tsurumeso's work and dedication! You can find tsurumeso's original command line version [here](https://github.com/tsurumeso/vocal-remover) +This project is a GUI version of the vocal remover created and posted by tsurumeso. This is a deep-learning-based tool that extracts the instrumental from a track containing vocals. This would not have been possible without tsurumeso's hard work and dedication! You can find tsurumeso's original command line version [here](https://github.com/tsurumeso/vocal-remover) ## Installation @@ -16,12 +16,12 @@ The application was made with Tkinter for cross platform compatibility, so this 2. Once Python has installed, open the Windows Command Prompt and run the following installs - - If you plan on doing conversions with your Nvidia GPU, please install the following - ``` -pip install torch==1.5.0+cu101 torchvision==0.6.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html +pip install torch==1.6.0+cu101 torchvision==0.7.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html ``` - If you don't have a compatible Nvidia GPU and plan on only using the CPU version please do not check the "GPU Conversion" option in the GUI and install the following - ``` -pip install torch==1.5.0+cpu torchvision==0.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html +pip install torch==1.6.0+cpu torchvision==0.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html ``` - The rest need to be installed as well - @@ -34,22 +34,22 @@ pip install numba==0.48.0 pip install SoundFile pip install soundstretch ``` -3. For the ability to convert mp3, mp4, m4a, and flac files, you'll need ffmpeg installed and configured! +3. For the ability to convert mp3, mp4, m4a, flac, along with other media formats, you'll need ffmpeg installed and configured! ### Getting the Vocal Remover GUI & Models -Download the latest version from [here](https://github.com/Anjok07/ultimatevocalremovergui/releases/tag/v2.2.0-GUI-Dev). +Download the latest version from [here](https://github.com/Anjok07/ultimatevocalremovergui/releases/tag/v2.2.0-GUI). ## Running the Vocal Remover Application GUI -1. Place this folder where ever you wish (I put mine in my documents folder) and open the file labeled "VocalRemover.py" (I reccomend you create a shortcut for the file labeled "VocalRemover.py" to your desktop) -2. Open the application +1. Extract the contents where ever you wish (I put mine in my documents folder) and open the file labeled "VocalRemover.py" (I recommend you create a shortcut for the file labeled "VocalRemover.py" to your desktop). +2. Open the application. ### Notes Regarding the GUI - - The application will automatically remember your "save to" path upon closing and reopening until you change it + - The application will automatically remember your "save to" path upon closing and re-opening until you change it  - You can select as many files as you like. Multiple conversions are supported! - - Conversions on wav files should always work with no issue. However, you will need to install and configure ffmpeg in order for conversions on mp3, mp4, m4a, and FLAC formats. If you select non-wav music files without having ffmpeg configured and attempt a conversion it will freeze and you will have to restart the application. + - Conversions on wav files should always work with no issue. However, you will need to install and configure ffmpeg in order for conversions on any other media file to work. If you select non-wav music files without having ffmpeg configured and attempt a conversion it will freeze and you will have to restart the application.  - Only check the GPU box if you have the Cuda driver installed for your Nvidia GPU. Most Nvidia GPU's released prior to 2015 or with less than 4GB's of V-RAM might not be compatible. -- The dropdown model menu consists of a provisional model that I trained with roughly 200 tracks. I included the option to add your own model as well if you've trained your own. Alternatively, you can also simply add a model to the models directory and restart the application, as it will automatically show there. +- The dropdown model menu consists of the models that I trained with roughly 700 pairs. I included the option to add your own model as well if you've trained your own. Alternatively, you can also simply add a model to the models directory and restart the application, as it will automatically show there. - The SR, N FFT, HOP LENGTH, and WINDOW SIZE parameters are set to the defaults. Those were the parameters used in training, so changing them may result in poor conversion performance unless the model is compatible with the changes made. Those are essentially advanced settings, so I recommend you leave them as is unless you know exactly what you're doing. - The Stacked Model is meant to clean up vocal residue left over in the form of vocal pinches and static. This model is only meant for instrumentals created via converted tracks that ran through one of the main models! - The "Stack Passes" option should only be used with the Stacked Model. This option allows you to set the amount of times you want a track to run through a model. The amount of times you need to run it through will vary greatly by track. Most tracks won't require any more than 2-5 passes. If you do 5 or more passes on a track you risk quality degradation. When doing stack passes the first and last "vocal" track will give you an idea of how much static was removed. From 97d5fbe13240e4feda673e2b43270eaa8a9db9a3 Mon Sep 17 00:00:00 2001 From: Dilan Boskan Date: Tue, 10 Nov 2020 15:21:27 +0100 Subject: [PATCH 10/12] Update issue templates Added ability to report bugs --- .github/ISSUE_TEMPLATE/bug_report.md | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. From acbc1782f88be775c709cccecbea0ea655656cb1 Mon Sep 17 00:00:00 2001 From: Dilan Boskan Date: Tue, 10 Nov 2020 15:25:46 +0100 Subject: [PATCH 11/12] Update issue templates Added enhancement template --- .github/ISSUE_TEMPLATE/enhancement-request.md | 20 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/enhancement-request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/enhancement-request.md b/.github/ISSUE_TEMPLATE/enhancement-request.md new file mode 100644 index 0000000..5927acc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement-request.md @@ -0,0 +1,20 @@ +--- +name: Enhancement Request +about: Suggest a way to improve the application +title: "[ENHANCEMENT]" +labels: 'Type: Enhancement' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7ebc39f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[ENHANCEMENT]" +labels: 'Type: Enhancement' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From bc174b05d17ae9f2838bb345552ccd2dcf894c98 Mon Sep 17 00:00:00 2001 From: Dilan Boskan Date: Tue, 10 Nov 2020 15:26:07 +0100 Subject: [PATCH 12/12] Delete feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 7ebc39f..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[ENHANCEMENT]" -labels: 'Type: Enhancement' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here.